IBM Bob과 MCP 통합

Model Context Protocol(MCP)은 호환성 문제를 해결하기 위해 등장했습니다. 일상생활에서도 호환성 문제는 다양한 불편을 초래합니다.

해외여행을 갔을 때 헤어 기기나 전자기기를 가져갔는데 플러그가 현지 콘센트와 맞지 않아 난감했던 경험이 있나요? 개발자의 관점에서는 AI 에이전트를 위해 API와 개발 툴을 구축했는데도 연결하거나 올바르게 호출하지 못하는 상황만큼 답답한 문제입니다. MCP는 바로 이러한 호환성 문제를 해결해 줍니다.

MCP란 무엇인가요?

2024년 Anthropic이 발표한 Model Context Protocol(MCP)은 AI 애플리케이션이 , 데이터 소스/데이터세트, 미리 정의된 템플릿과 같은 외부 서비스와 효과적으로 통신할 수 있도록 하는 표준화 계층 역할을 합니다. MCP는 AI와 툴 간 상호작용을 위한 개방형 표준이자 커넥터 역할을 합니다. MCP 아키텍처는 다음과 같은 세 가지 핵심 구성 요소로 이루어져 있습니다.

  1. MCP Host: AI 애플리케이션은 사용자 요청을 수신하고 MCP를 통해 컨텍스트에 액세스합니다.
  2. MCP Client: MCP 에코시스템에서 Host와 Server 간의 통신은 반드시 Client를 통해 이루어집니다. Client는 Host 내부에 있으며 사용자 요청을 개방형 프로토콜에서 처리할 수 있는 구조화된 형식으로 변환합니다.
  3. MCP Server: 사용자 요청을 서버 작업으로 변환하고, 이를 통해 LLM에 컨텍스트를 제공하는 외부 서비스입니다. MCP 서버 통합(또는 MCP 커넥터)의 예로는 Slack, GitHub, Git, Docker, 웹 검색 등이 있습니다.
MCP 아키텍처

MCP 통합에 IBM Bob을 사용하는 이유

먼저 IBM® Bob이 무엇인지 살펴보겠습니다. IBM Bob은 생성형 AI 기반의 통합 개발 환경(IDE)이자 현대화 지원 도우미입니다. Bob은 사용자의 의도와 코드베이스, 조직의 표준을 이해하는 AI 중심 IDE이자 페어 개발자라고 생각하면 됩니다.

특히 초보 개발자의 경우 MCP 서버를 처음부터 직접 구축하는 데는 많은 시간이 소요될 수 있습니다. 이 튜토리얼에서는 몇 가지 간단한 자연어 프롬프트만으로 IBM Bob을 사용해 이 워크플로를 빠르게 시작하는 방법을 살펴보겠습니다.

MCP 통합은 외부 툴 및 서비스와 연결하여 Bob의 기능을 확장합니다. 이 통합은 글로벌 수준(모든 워크스페이스에 적용) 또는 프로젝트 수준(.Bob/mcp.json을 통해 팀과 공유 가능)에서 구성할 수 있습니다. MCP는 두 가지 전송 방식을 지원합니다. 하나는 로컬의 저지연 서버를 위한 표준 입출력(STDIO)이고, 다른 하나는 HTTP/HTTPS를 통해 액세스하는 원격 MCP 서버를 위한 서버 전송 이벤트(SSE)입니다. 사용자는 Bob 설정 메뉴에서 JSON 파일을 사용해 서버를 구성하고, 명령, 환경 변수 및 자동 승인할 툴을 정의할 수 있습니다. 두 전송 방식 모두 Bob의 MCP 설정 패널에서 서버를 활성화하거나 비활성화하고, 특정 툴을 자동 승인하며, 서버 운영을 관리할 수 있습니다.

전제조건

  • IBM Bob IDE가 설치되어 있어야 합니다. IBM Bob을 미리 사용하려면 등록하세요.

단계

시작해 보겠습니다. GitHub에서 이 튜토리얼을 따라 하고 싶다면 리포지터리를 확인하세요.

1단계. Bob 설정하기

1. 먼저 사전 요구 사항으로 설치한 IBM Bob IDE를 열고 새로운 AI 코딩 도우미의 레이아웃을 살펴봅니다.

IBM Bob - IDE 시작

2. MCP 설정 패널에 액세스하려면 채팅 창 오른쪽 상단의 톱니바퀴 아이콘 옆에 있는 점 3개를 클릭합니다. 그런 다음 드롭다운 메뉴에서 MCP servers 를 선택합니다.

IBM Bob - Marketplace의 MCP 서버

여기에서는 MCP를 전역 또는 서버별로 활성화하거나 비활성화하고, 툴(예: 자동 승인, 삭제, 다시 시작)을 관리할 수 있습니다. 또한 Bob Marketplace에서 커뮤니티 서버를 살펴보거나 MCP SDK를 사용하여 직접 서버를 구축할 수도 있습니다.

Bob Marketplace에서 서버를 설치한 경우 구성은 두 가지 수준으로 설정할 수 있습니다. 전역(모든 워크스페이스에 적용되며 mcp_settings.json에 저장) 또는 프로젝트별(프로젝트 루트의 .Bob/mcp.json에 저장되며 버전 관리를 통해 팀과 쉽게 공유 가능)입니다.

프로젝트 수준 설정은 전역 설정보다 우선 적용되므로 다양한 사용 사례에 맞게 MCP 동작을 유연하게 조정할 수 있습니다. 이러한 구성을 관리하려면 Bob 설정 메뉴에서 JSON 파일을 직접 편집하여 명령, 환경 변수, 자동 승인할 툴 등의 서버 세부 정보를 정의할 수 있습니다. 이 튜토리얼에서는 SDK를 사용합니다.

3. Bob으로 사용자 지정 MCP 서버를 생성할 수 있도록 Enable MCP Server Creation 설정이 활성화되어 있는지 확인합니다.

4. 프로젝트를 설정할 디렉터리가 있다면 IDE에서 직접 열거나 채팅 창에서 Bob에게 열도록 요청할 수 있습니다.

2단계. 가상 환경 활성화

  1. 이제 설정 패널을 닫고 채팅 창으로 돌아가겠습니다.
  2. Bob에는 plan, code, advanced, ask, orchestrator와 같은 여러 모드가 있는 것을 확인할 수 있습니다. 이 프로젝트에서는 모드를 advanced로 설정합니다.
IBM Bob - 고급 모드

3. 프로젝트 간 종속성이 서로 충돌하지 않도록 프로젝트의 종속성을 격리하기 위해 Python 가상 환경을 생성하는 것이 일반적입니다. 이를 위해 다음 프롬프트를 입력합니다. “In this directory, activate a Python virtual environment”.

IBM Bob - 가상 환경 생성 프롬프트

4. Bob이 일련의 터미널 명령을 실행하는 것을 확인할 수 있습니다. 실행되는 명령은 다음과 비슷합니다.

python3 -m venv venv
source venv/bin/activate

Bob이 각 명령을 실시간으로 실행하기 전에 검토하고 승인하거나 거부할 수 있도록 자동 승인 토글은 비활성화된 상태로 유지하는 것이 좋습니다.

IBM Bob - 가상 환경

잘 되었습니다. Bob이 venv/ 디렉터리에 새 가상 환경을 생성하고 성공적으로 활성화했습니다.

3단계. Bob이 계획 생성

이제 가상 환경이 준비되었으므로 MCP 서버 생성을 시작하겠습니다. Bob이나 다른 AI 모델 또는 AI 도우미에게 코드 생성을 요청할 때는 중요한 세부 정보를 함께 제공하는 것이 좋습니다. Bob이 어떻게 동작하는지 확인하기 위해 다음 프롬프트를 입력해 보겠습니다.

"arXiv에 대한 읽기 전용 액세스를 제공하는 MCP 서버를 생성해 줘." 서버는 다음 요구 사항을 충족해야 합니다.

  • arXiv 논문을 검색할 수 있는 검색 툴을 제공합니다.
  • 검색 결과는 논문의 메타데이터와 초록만 제공하고(PDF 제외)
  • 검색어와 검색 결과 수에 합리적인 제한을 적용합니다.
  • 응답을 깔끔하고 구조화된 스키마로 정규화합니다.”
IBM Bob - 할 일 목록 생성

이 간단한 프롬프트 하나만으로도 Bob은 작업을 이해하고 작업을 완료하기 위한 'to-do list'를 작성하는 데 필요한 충분한 정보를 얻을 수 있습니다. 이 목록에는 MCP 서버 생성뿐만 아니라 구성 및 테스트까지 포함되어 있다는 점에 주목하세요. 정말 편리하죠.

참고로 이 튜토리얼에서는 API 키나 인증 없이 바로 사용할 수 있는 간단한 예제로 arXiv API를 사용합니다. 하지만 이는 하나의 예시일 뿐이며, Bob은 필요한 권한이 필요한 더 복잡한 서버도 충분히 처리할 수 있습니다.

4단계. Bob이 사용자 지정 MCP 서버를 구축합니다.

  1. 이제 Bob은 arXiv MCP 서버를 구축하기 위한 작업을 시작할 준비가 되었습니다. 먼저 Bob은 다음 명령을 실행하여 프로젝트 구조를 직접 생성합니다.
mkdir -p arxiv-server/src

각 명령이 실행되기 전에 해당 작업을 승인하거나 거부할 수 있습니다. 명령이 자동으로 실행된다면 자동 승인 토글이 활성화되어 있는지 확인하세요.

2. 다음으로 Bob은 arxiv-server/package.json 파일을 생성합니다. 이 파일은 Node.js 프로젝트의 구성 허브 역할을 합니다. 구체적으로 이 파일에는 프로젝트 메타데이터(예: 이름, 버전, 설명 등), 종속성, 스크립트 및 프로젝트 설정이 포함되어 있습니다. 생성된 package.json 파일에 어떤 내용이 포함되어 있는지 살펴보겠습니다.

{
  "name": "arxiv-server",
  "version": "0.1.0",
  "description": "MCP server for read-only access to arXiv papers",
  "type": "module",
  "bin": {
    "arxiv-server": "./build/index.js"
  },
  "files": [
    "build"
  ],
  "scripts": {
    "build": "tsc && node -e \"require('fs').chmodSync('build/index.js', '755')\"",
    "prepare": "npm run build",
    "watch": "tsc --watch"
  },
  "keywords": [
    "mcp",
    "arxiv",
    "research",
    "papers"
  ],
  "dependencies": {
    "@modelcontextprotocol/sdk": "^1.0.4",
    "axios": "^1.7.9",
    "zod": "^3.24.1"
  },
  "devDependencies": {
    "@types/node": "^22.10.5",
    "typescript": "^5.7.3"
  }
}
  1. 다음으로 Bob은 컴파일러가 TypeScript 코드를 JavaScript로 변환하는 방식을 정의하는 arxiv-server/tsconfig.json 파일을 생성합니다.
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "Node16",
    "moduleResolution": "Node16",
    "outDir": "./build",
    "rootDir": "./src",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "resolveJsonModule": true,
    "declaration": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "build"]
}

4. 다음으로 arXiv 검색 기능을 구현한 기본 서버는 arxiv-server/src/index.ts에 저장됩니다. 이 파일의 역할은 다음과 같습니다.

  • 필요한 라이브러리를 가져옵니다.
  • arXiv API 응답의 구조를 정의합니다.
  • arXiv API는 JSON이 아닌 XML을 반환하므로, XML 응답을 구조화된 JavaScript 객체로 변환합니다.
  • 다음 정보를 추출합니다.
    • 논문 정보(제목, 저자, 초록 등)
    • 페이지 매김 정보(총 결과 수, 시작 인덱스, 페이지당 항목 수)
  • 파싱된 데이터를 터미널에 표시할 수 있는 읽기 쉬운 문자열 형식으로 변환합니다.
  • 검색어를 입력받고 선택적 필터를 지원하며, arXiv API에서 데이터를 가져와 형식화된 결과를 반환하는 검색 함수를 정의합니다(오류가 발생하면 오류를 반환).
  • 서버를 시작합니다.
#!/usr/bin/env node
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
import axios from 'axios';

// Define types for arXiv API responses
interface ArxivEntry {
  id: string;
  title: string;
  summary: string;
  authors: Array<{ name: string }>;
  published: string;
  updated: string;
  categories: string[];
  primary_category: string;
  links: Array<{ href: string; rel: string; type?: string }>;
}

interface ArxivSearchResult {
  entries: ArxivEntry[];
  totalResults: number;
  startIndex: number;
  itemsPerPage: number;
}

// Create an MCP server
const server = new McpServer({
  name: "arxiv-server",
  version: "0.1.0"
});

// Create axios instance for arXiv API
const arxivApi = axios.create({
  baseURL: 'http://export.arxiv.org/api',
  timeout: 30000,
});

/**
 * Parse arXiv API XML response to JSON
 */
function parseArxivXML(xmlData: string): ArxivSearchResult {
  const entries: ArxivEntry[] = [];
  
  // Extract total results
  const totalResultsMatch = xmlData.match(/<opensearch:totalResults[^>]*>(\d+)<\/opensearch:totalResults>/);
  const totalResults = totalResultsMatch ? parseInt(totalResultsMatch[1]) : 0;
  
  const startIndexMatch = xmlData.match(/<opensearch:startIndex[^>]*>(\d+)<\/opensearch:startIndex>/);
  const startIndex = startIndexMatch ? parseInt(startIndexMatch[1]) : 0;
  
  const itemsPerPageMatch = xmlData.match(/<opensearch:itemsPerPage[^>]*>(\d+)<\/opensearch:itemsPerPage>/);
  const itemsPerPage = itemsPerPageMatch ? parseInt(itemsPerPageMatch[1]) : 0;
  
  // Extract entries
  const entryRegex = /<entry>([\s\S]*?)<\/entry>/g;
  let entryMatch;
  
  while ((entryMatch = entryRegex.exec(xmlData)) !== null) {
    const entryXml = entryMatch[1];
    
    // Extract ID
    const idMatch = entryXml.match(/<id>([^<]+)<\/id>/);
    const id = idMatch ? idMatch[1] : '';
    
    // Extract title
    const titleMatch = entryXml.match(/<title>([^<]+)<\/title>/);
    const title = titleMatch ? titleMatch[1].trim().replace(/\s+/g, ' ') : '';
    
    // Extract summary
    const summaryMatch = entryXml.match(/<summary>([^<]+)<\/summary>/);
    const summary = summaryMatch ? summaryMatch[1].trim().replace(/\s+/g, ' ') : '';
    
    // Extract authors
    const authors: Array<{ name: string }> = [];
    const authorRegex = /<author>\s*<name>([^<]+)<\/name>/g;
    let authorMatch;
    while ((authorMatch = authorRegex.exec(entryXml)) !== null) {
      authors.push({ name: authorMatch[1].trim() });
    }
    
    // Extract published date
    const publishedMatch = entryXml.match(/<published>([^<]+)<\/published>/);
    const published = publishedMatch ? publishedMatch[1] : '';
    
    // Extract updated date
    const updatedMatch = entryXml.match(/<updated>([^<]+)<\/updated>/);
    const updated = updatedMatch ? updatedMatch[1] : '';
    
    // Extract categories
    const categories: string[] = [];
    const categoryRegex = /<category[^>]+term="([^"]+)"/g;
    let categoryMatch;
    while ((categoryMatch = categoryRegex.exec(entryXml)) !== null) {
      categories.push(categoryMatch[1]);
    }
    
    const primary_category = categories[0] || '';
    
    // Extract links
    const links: Array<{ href: string; rel: string; type?: string }> = [];
    const linkRegex = /<link[^>]+href="([^"]+)"[^>]+rel="([^"]+)"(?:[^>]+type="([^"]+)")?/g;
    let linkMatch;
    while ((linkMatch = linkRegex.exec(entryXml)) !== null) {
      links.push({
        href: linkMatch[1],
        rel: linkMatch[2],
        type: linkMatch[3]
      });
    }
    
    entries.push({
      id,
      title,
      summary,
      authors,
      published,
      updated,
      categories,
      primary_category,
      links
    });
  }
  
  return {
    entries,
    totalResults,
    startIndex,
    itemsPerPage
  };
}

/**
 * Format search results for display
 */
function formatSearchResults(result: ArxivSearchResult): string {
  let output = `Found ${result.totalResults} results (showing ${result.entries.length})\n\n`;
  
  result.entries.forEach((entry, index) => {
    output += `${index + 1}. ${entry.title}\n`;
    output += `   ID: ${entry.id}\n`;
    output += `   Authors: ${entry.authors.map(a => a.name).join(', ')}\n`;
    output += `   Published: ${entry.published}\n`;
    output += `   Categories: ${entry.categories.join(', ')}\n`;
    output += `   Abstract: ${entry.summary.substring(0, 300)}${entry.summary.length > 300 ? '...' : ''}\n`;
    
    // Find abstract link (not PDF)
    const abstractLink = entry.links.find(l => l.rel === 'alternate');
    if (abstractLink) {
      output += `   URL: ${abstractLink.href}\n`;
    }
    output += '\n';
  });
  
  return output;
}

// Add a tool for searching arXiv papers
server.tool(
  "search_arxiv",
  {
    query: z.string().describe("Search query (supports arXiv query syntax)"),
    max_results: z.number().min(1).max(50).optional().describe("Maximum number of results to return (1-50, default: 10)"),
    start: z.number().min(0).optional().describe("Starting index for pagination (default: 0)"),
    sort_by: z.enum(["relevance", "lastUpdatedDate", "submittedDate"]).optional().describe("Sort order (default: relevance)"),
    sort_order: z.enum(["ascending", "descending"]).optional().describe("Sort direction (default: descending)")
  },
  async ({ query, max_results = 10, start = 0, sort_by = "relevance", sort_order = "descending" }) => {
    try {
      // Enforce reasonable limits
      const limitedMaxResults = Math.min(max_results, 50);
      const limitedStart = Math.max(start, 0);
      
      // Build query parameters
      const params: Record<string, string | number> = {
        search_query: query,
        start: limitedStart,
        max_results: limitedMaxResults,
      };
      
      if (sort_by) {
        params.sortBy = sort_by;
      }
      
      if (sort_order) {
        params.sortOrder = sort_order;
      }
      
      const response = await arxivApi.get('/query', { params });
      
      // Parse XML response
      const result = parseArxivXML(response.data);
      
      // Format results
      const formattedResults = formatSearchResults(result);
      
      return {
        content: [
          {
            type: "text",
            text: formattedResults,
          },
        ],
      };
    } catch (error) {
      if (axios.isAxiosError(error)) {
        return {
          content: [
            {
              type: "text",
              text: `arXiv API error: ${error.response?.data?.message ?? error.message}`,
            },
          ],
          isError: true,
        };
      }
      throw error;
    }
  }
);

// Start receiving messages on stdin and sending messages on stdout
const transport = new StdioServerTransport();
await server.connect(transport);
console.error('arXiv MCP server running on stdio');

// Bob으로 생성됨

이 단계에서 서버에 API 키가 필요한 경우 Bob이 해당 정보를 요청합니다.

5. 다음으로 Bob은 다음 명령을 실행하여 arxiv-server 디렉터리에 필요한 종속성을 설치합니다.

cd arxiv-server && npm install
  1. 이제 Bob은 설정 파일에 MCP 서버 구성을 추가할 준비가 되었습니다. 전역 MCP 서버는 mcp_settings.json에서 구성하고, 프로젝트 수준 MCP 서버는 .Bob/mcp.json에서 구성합니다. 두 유형의 차이점은 전역 서버는 모든 워크스페이스에 적용되는 반면, 프로젝트 수준 서버 구성은 프로젝트 루트에 저장된다는 것입니다. 이 튜토리얼에서는 프로젝트를 전역 MCP 서버로 저장하지만, 필요에 가장 적합한 옵션을 선택하면 됩니다.
{ 
	"mcpServers": {}
	"mcpServers": { 
		"arxiv": { 
			"command": "node", 
			"args": [ "/here/is/the/path/to/arxiv-server/build/index.js" 
				], 
			"disabled": false, 
			"alwaysAllow": [], 
			"disabledTools": [] 
		} 
	}
}

이로써 Bob의 MCP 서버 설정 과정이 완료됩니다.

5단계. MCP 서버 테스트

IBM Bob - 서버 테스트

'to-do list' 작업 시리즈를 완료하기 위해 Bob은 MCP 서버를 테스트합니다. 앞의 스크린샷에서 볼 수 있듯이 Bob은 MCP 서버의 search_arxiv 툴을 질의하여 관련성순으로 정렬된 양자 컴퓨팅 논문 3편을 찾습니다.

아래쪽 캐럿을 클릭해 창을 펼치면 성공적으로 실행된 것을 확인할 수 있으며, Bob은 이어서 또 다른 테스트를 수행합니다. 이번에는 제출일 내림차순으로 정렬된 머신 러닝 논문 2편을 검색합니다. 다른 매개변수를 사용했음에도 이 MCP 툴 호출 역시 성공적으로 실행되었습니다.

IBM Bob - 작업 완료

테스트가 모두 성공적으로 완료되었으므로 Bob은 이제 모든 하위 작업을 완료했습니다.

Bob은 이미 MCP 서버를 테스트해 두었습니다. 이제 채팅 창에서 직접 몇 가지 검색을 수행해 보면서 Bob이 적절한 검색어와 필요한 매개변수를 스스로 도출하는지 확인해 보겠습니다.

Bob에게 "LLM 에이전트 추적에 관한 최신 논문을 찾아줘."라고 요청합니다.

IBM Bob - LLM 에이전트 추적 검색

Bob은 프롬프트에서 적절한 검색어를 스스로 추출하고, 검색 품질을 높이기 위해 추가 키워드를 덧붙였습니다. 또한 검색 결과의 최대 개수를 10개로 설정하고 논문을 관련성순으로 정렬했습니다. 잘 되었습니다.

검색을 한 번 더 수행해 보겠습니다.

IBM Bob - MCP 서버를 사용한 Bob 질의

흥미롭게도 Bob은 원하지 않는 검색 결과를 확인하자 검색어를 자동으로 수정했습니다. Bob은 툴 호출을 무작정 실행하는 것이 아니라, 도움을 주는 에이전트로서 사용자와 협력합니다. 이러한 과정을 두 차례 반복한 끝에 Bob은 처음 의도한 작업에 잘 부합하는 여러 논문을 찾아주었습니다.

6단계. 서버 문서화

많은 오픈 소스 MCP 서버에는 다른 사용자도 쉽게 시작할 수 있도록 문서가 함께 제공됩니다. 다음 프롬프트를 채팅 창에 붙여 넣습니다.

"이 디렉터리에 이 MCP 서버를 설명하는 README.md 파일을 생성해 줘. 설정 및 사용 방법도 포함해."

IBM Bob - README 생성 작업

간단한 프롬프트 하나만으로 Bob은 arXiv MCP 서버를 이해하고, 설치하고, 구성하고, 문제를 해결하고, 사용하는 데 필요한 모든 내용을 담은 포괄적인 README.md 문서를 생성했습니다.

7단계. (선택 사항) watsonx Orchestrate 에이전트 만들기

이 MCP 서버에 액세스할 수 있는 연구 특화 AI 에이전트watsonx Orchestrate로 구축해 보고 싶으신가요? Bob은 간단한 프롬프트 하나만으로 에이전트를 생성할 수 있습니다. 먼저 1단계에서 살펴본 MCP 설정 패널의 Marketplace에서 미리 빌드된 watsonx Orchestrate ADK 서버를 설치합니다. 그런 다음 다음 명령을 입력합니다.

"이 arXiv MCP 서버를 사용하는 watsonx Orchestrate 에이전트를 생성해 줘."

로컬에서 watsonx Orchestrate 서비스가 실행 중이라면 Bob이 필요한 명령을 대신 실행해 줍니다. 나중에 직접 명령을 실행하고 싶다면 Bob이 필요한 스크립트를 작성하고 필요한 명령도 함께 문서화해 줍니다.

IBM Bob - WXO 에이전트 생성

Bob이 생성한 내용을 더 잘 이해하기 위해 각 파일을 살펴보겠습니다. 먼저 toolkit-config.yaml 파일을 살펴보겠습니다. 이 파일은 외부 툴이나 MCP 서버를 watsonx Orchestrate 환경에 구성하고 통합하기 위한 정의 파일 역할을 합니다. MCP 서버가 올바르게 식별되고 설명되어 있는 것을 확인할 수 있습니다.

kind: mcp
name: arxiv-toolkit
description: Toolkit for searching arXiv research papers. arXiv 데이터베이스의 논문 메타데이터, 초록 및 출판 정보에 액세스할 수 있도록 합니다.package_root: /local/path/to/arxiv-serverlanguage: nodecommand: node /local/path/to/arxiv-server/arxiv-server/build/index.jstools:- "*"# Bob으로 생성

다음으로 research-assistant-agent.yaml 파일을 열어보겠습니다.

name: research-assistant
kind: native
description: arXiv에서 학술 논문을 찾고 요약하는 데 도움을 주는 AI 연구 도우미입니다. 학술 문헌 검색, 연구 결과 설명 및 인용 정보 제공에 특화되어 있습니다.
title: 연구 도우미
instructions: |
당신은 arXiv의 학술 문헌 검색을 전문으로 하는 연구 도우미입니다.
## 주요 기능
- 모든 과학 분야의 주제에 대해 arXiv 논문을 검색합니다.
- 초록을 바탕으로 연구 결과를 이해하기 쉬운 언어로 요약합니다.
- 주요 저자와 연구 동향을 파악합니다.
- 관련 논문과 연구 주제를 제안합니다.
- arXiv ID와 URL을 포함한 올바른 인용 정보를 제공합니다.
## 사용자에게 응답할 때
1. 항상 arXiv ID와 논문의 직접 URL을 제공합니다.
2. 초록을 이해하기 쉬운 언어로 요약합니다.
3. 주요 기여와 연구 성과를 강조합니다.
4. 관련이 있는 경우 후속 검색을 제안합니다.
5. 간결하면서도 충분한 정보를 제공합니다.
## search_arxiv 툴 사용
사용 가능한 매개변수:
- query (필수): arXiv 검색 구문을 사용하는 검색어
- max_results (선택 사항): 검색할 논문 수(1~50, 기본값: 10)
- start (선택 사항): 페이지 매김을 위한 시작 인덱스(기본값: 0)
- sort_by (선택 사항): "relevance", "submittedDate" 또는 "lastUpdatedDate"
- sort_order (선택 사항): "ascending" 또는 "descending"
## 고급 검색 구문
검색어에서 다음 연산자를 사용할 수 있습니다.
- ti:keyword 
- 제목에서 검색
- au:author 
- 저자 이름으로 검색- abs:keyword 
- 초록에서 검색
- cat:category 
- 카테고리로 필터링(예: cs.AI, quant-ph, math.CO)
- AND, OR, ANDNOT 
- 불리언 연산자
예시:
- "ti:transformer AND cat:cs.LG" 
- 머신 러닝 분야의 Transformer 논문
- "au:Hinton" - Geoffrey Hinton의 논문
- "quantum computing AND cat:quant-ph" 
- 양자물리학 분야의 양자 컴퓨팅 논문
## 주요 카테고리
- cs.AI 
- 인공지능
- cs.LG - 머신 러닝
- cs.CL - 자연어 처리
- cs.CV - 컴퓨터 비전
- quant-ph - 양자물리학
- math.CO - 조합론
- stat.ML - 머신 러닝(통계)
## 응답 형식논문를 소개할 때는 다음 형식을 사용합니다.
**"논문 제목"**
- 저자: [저자 이름]
- 출판일: [날짜]
- 카테고리: [카테고리]
- 요약: [초록의 간략한 요약]
- [논문 보기](arXiv URL)## 예외 상황 처리
- 검색 결과가 없는 경우: 대체 검색어나 더 포괄적인 검색어를 제안합니다.
- 검색 결과가 너무 많은 경우: 카테고리나 날짜 필터를 사용하여 검색 범위를 좁히도록 권장합니다.
- 사용자가 PDF를 요청하는 경우: 메타데이터만 제공할 수 있음을 설명하고, 논문에 접근할 수 있는 URL을 함께 제공합니다.
- 검색어가 불명확한 경우: 연구 분야나 구체적인 관심사에 대해 확인 질문을 합니다.

tools:
- search_arxivconfig:hidden: falseenable_cot: true

tags:
- research
- academic
- papers
- arxiv
- literature
-search

# Bob으로 생성됨

이 YAML 파일은 arXiv를 검색하고, 논문을 요약하며, 구조화된 형식으로 인용 정보를 제공하여 학술 연구를 간소화하는 전문 AI 에이전트인 Research Assistant를 구성합니다. 질의 구문과 툴 사용법부터 응답 형식과 예외 상황 처리까지 에이전트의 동작을 안내하는 자세한 지침이 포함되어 있습니다. 또한 search_arxiv 툴을 활용하여 과학 문헌을 효율적으로 검색하고 제공하는 방법도 자세히 설명되어 있습니다. 마지막으로 setup-instructions.md 파일에는 arXiv MCP 서버를 watsonx Orchestrate와 통합하는 데 필요한 모든 정보가 포함되어 있습니다. 이 파일에는 터미널에서 실행할 명령, 테스트, 문제 해결 팁, 대체 Python 스크립트 등 다양한 정보가 포함되어 있습니다.

결론

이 튜토리얼에서는 AI 중심 IDE이자 페어 개발자인 IBM Bob을 사용하여 학술 연구를 위한 MCP 통합 과정을 간소화했습니다. arXiv.org 리포지터리에서 논문을 검색하고 가져올 수 있는 확장 가능한 MCP 서버를 효율적으로 구축했습니다. 이제 이 솔루션은 연구 커뮤니티를 위해 오픈 소스로 공개하거나, 지식 탐색을 강화하기 위해 엔터프라이즈 애플리케이션에 배포할 수 있을 만큼 프로덕션 환경에 사용할 준비가 되었습니다.

IBM Bob의 진정한 강점은 복잡한 개발 작업을 직관적인 프롬프트 기반 워크플로로 전환하는 능력에 있습니다. 몇 가지 전략적인 프롬프트만으로 Bob은 프로토타입 개발을 가속화하고, 반복적인 코드를 줄이며, 최적화 방안까지 제안하여 구현보다 혁신에 집중할 수 있도록 지원합니다.

Bob의 기능을 계속 살펴보면서 MCP 서버를 어떻게 더욱 개선할 수 있을지 생각해 보세요. 예를 들어 고급 필터링, 실시간 업데이트 또는 PubMed나 IEEE Xplore와 같은 다른 학술 데이터베이스와의 통합 기능을 추가할 수 있습니다. 이 모든 기능과 그 이상의 작업도 IBM Bob에 몇 가지 간단한 프롬프트를 입력하는 것만으로 구현할 수 있습니다.

다음 단계로 나아갈 준비가 되셨나요? MCP 서버를 직접 사용자 지정해 보거나 Bob의 기능을 더 깊이 살펴보며 더 많은 자동화 가능성을 활용해 보세요. 즐거운 코딩 되세요!

작성자

Anna Gutowska

AI Engineer, Developer Advocate

IBM

관련 솔루션
비즈니스용 AI 에이전트

생성형 AI로 워크플로와 프로세스를 자동화하는 강력한 AI 어시스턴트 및 에이전트를 구축, 배포, 관리하세요.

    watsonx Orchestrate 살펴보기
    IBM AI 에이전트 솔루션

    믿을 수 있는 AI 솔루션으로 비즈니스의 미래를 설계하세요.

    AI 에이전트 솔루션 살펴보기
    IBM Consulting AI 서비스

    IBM Consulting AI 서비스는 기업이 AI 활용 방식을 재구상하여 혁신을 달성하도록 지원합니다.

    인공 지능 서비스 살펴보기
    다음 단계 안내

    사전 구축된 앱과 스킬을 사용자 정의하든, AI 스튜디오를 사용하여 맞춤형 에이전틱 서비스를 구축하고 배포하든, IBM watsonx 플랫폼이 모든 것을 지원합니다.

    1. watsonx Orchestrate 살펴보기
    2. watsonx.ai 살펴보기