Model Context Protocol (MCP) surgió de la cuestión de la incompatibilidad. En nuestra vida cotidiana, la incompatibilidad nos incomoda de varias maneras.
¿Alguna vez le ha pasado que, al viajar al extranjero, se ha llevado un aparato para el pelo o un dispositivo electrónico y se ha dado cuenta de que el enchufe no es compatible con la toma de corriente? Desde la perspectiva de los desarrolladores, este problema es tan frustrante como construir API y herramientas de desarrollo para su agente de IA que no parece poder conectarse ni invocar correctamente. Ahí es exactamente donde MCP alivia este problema de incompatibilidad.
Model Context Protocol (MCP), introducido por Anthropic en 2024, sirve como una capa de estandarización para que las aplicaciones de IA se comuniquen eficazmente con servicios externos como herramientas, fuentes de datos/conjuntos de datos y plantillas predefinidas. MCP sirve esencialmente como un estándar abierto y un conector para las interacciones entre la IA y las herramientas. La arquitectura MCP se puede dividir en tres componentes arquitectónicos clave:
Primero, ¿qué es IBM Bob? IBM Bob es un entorno de desarrollo de integración (IDE) y modernización impulsado por IA generativa. Piense Bob como su desarrollador de pares e IDE que da prioridad a la IA: una herramienta que entiende su intención, su base de código y los estándares de su organización.
Construir su propio servidor MCP desde cero puede llevar mucho tiempo, especialmente para desarrolladores principiantes. En su lugar, en este tutorial, exploraremos cómo iniciar rápidamente este flujo de trabajo con IBM Bob utilizando unas sencillas instrucciones en lenguaje natural.
La integración de MCP amplía las funcionalidades de Bob al conectarse con herramientas y servicios externos, configurables a nivel global (se aplica a todos los espacios de trabajo) o a nivel de proyecto (compartible con el equipo a través de .Bob/mcp.json). MCP admite dos tipos de transporte: entrada/salida (input/output) estándar (STDIO) para servidores locales de baja latencia y eventos enviados por el servidor (SSE) para servidores MCP remotos accesibles a través de HTTP/HTTPS. Los usuarios pueden configurar servidores con archivos JSON en el menú de configuración de Bob, definiendo comandos, variables de entorno y herramientas autoaprobadas. Ambos tipos de transporte le permiten activar o desactivar servidores, aprobar automáticamente herramientas específicas y gestionar su operación a través del panel de configuración de MCP de Bob.
Comencemos. Si prefiere seguir este tutorial en GitHub, eche un vistazo a nuestro repositorio.
1. Abra el IDE de IBM Bob que instaló como requisito previo y familiarícese con el diseño de su nuevo compañero de codificación de IA.
2. Para acceder al panel de configuración de MCP, haga clic en los 3 puntos junto al icono de engranaje en la esquina superior derecha de la ventana de chat. Luego, seleccione servidores MCP en el menú desplegable.
Aquí, podemos habilitar o deshabilitar MCP globalmente o por servidor y administrar herramientas (por ejemplo, aprobación automática, eliminación o reinicio). También podemos explorar servidores comunitarios a través de Bob Marketplace o crear los nuestros propios con el SDK de MCP.
Si decide instalar un servidor desde el Bob Marketplace, notará que las configuraciones pueden configurarse en dos niveles: global (almacenado en
La configuración a nivel de proyecto anula la configuración global, lo que le brinda flexibilidad para adaptar el comportamiento de MCP a diferentes casos de uso. Para gestionar estas configuraciones, puede editar archivos JSON directamente a través del menú de configuración de Bob, donde define detalles del servidor como comandos, variables de entorno y herramientas autoaprobadas. En este tutorial, utilizaremos el SDK.
3. Asegúrese de que la opción Habilitar la creación de servidores MCP esté activa para crear servidores MCP personalizados con Bob.
4. Si tiene un directorio preferido para configurar su proyecto, puede abrirlo usted mismo dentro del IDE o dejar que Bob lo haga por usted en la ventana de chat.
3. Es una práctica común crear entornos virtuales de Python para aislar las dependencias de un proyecto, de modo que los diferentes proyectos no entren en conflicto entre sí. Para ello, introduzca la instrucción: “En este directorio, activa un entorno virtual de Python”.
4. Deberías ver a Bob ejecutar una serie de comandos de terminal. Es probable que estos comandos se parezcan a:
Le recomendamos que mantenga desactivado el conmutador de aprobación automática para poder aprobar o denegar cada comando antes de que Bob lo ejecute en tiempo real.
Genial. Bob creó y activó correctamente un nuevo entorno virtual en el directorio
Con nuestro entorno virtual configurado, ahora podemos pasar a la creación del servidor MCP. Al pedir a Bob que genere código, o cualquier modelo de IA o asistente de IA, es útil incluir detalles importantes. Para ver a Bob en acción, enviemos la instrucción:
"Crea un servidor MCP que proporcione acceso de solo lectura a arXiv. El servidor debe:
Con esta sencilla instrucción, Bob dispone de información suficiente tanto para comprender la tarea como para elaborar una "lista de tareas" con los pasos necesarios para llevarla a cabo. Fíjese en que la lista incluye no solo la creación del servidor MCP, sino también su configuración y las pruebas. Genial.
Tenga en cuenta que usamos la API de arXiv en este tutorial como un ejemplo sencillo que no requiere ninguna clave de API ni autenticación para empezar. Sin embargo, este es un ejemplo y Bob también está bien equipado para gestionar servidores más complejos con los permisos necesarios.
Antes de ejecutar cada comando, podemos aprobar o denegar la acción. Si observa que los comandos se ejecutan automáticamente, es posible que tenga activado el conmutador de aprobación automática.
2. A continuación, Bob crea un archivo
{
"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"
}
}
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. Luego, la implementación del servidor principal con la funcionalidad de búsqueda de arXiv se almacena en
#!/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');
// Made with Bob
En esta fase, si tu servidor requiere alguna clave API, Bob te la pedirá.
5. Como próximos pasos, Bob instala las dependencias dentro del directorio arxiv-server ejecutando el siguiente comando.
mcp_settings.json.Bob/mcp.json{
"mcpServers": {}
"mcpServers": {
"arxiv": {
"command": "node",
"args": [ "/here/is/the/path/to/arxiv-server/build/index.js"
],
"disabled": false,
"alwaysAllow": [],
"disabledTools": []
}
}
}
Esta información completa la serie de pasos que Bob sigue para configurar el servidor MCP.
Para completar la serie de tareas de la "lista de tareas pendientes", Bob prueba el servidor MCP. Como se ve en la captura de pantalla anterior, Bob consulta la herramienta
Tras la ejecución satisfactoria, que puedes ver haciendo clic en la flecha hacia abajo para ampliar la ventana, Bob realizó otra prueba. Esta vez, la consulta es para 2 artículos de machine learning ordenados por fecha de envío descendente. Incluso con el uso de los diferentes parámetros, esta llamada a la herramienta MCP también se ha ejecutado correctamente.
Dado el éxito de las pruebas, Bob ha completado todas las subtareas.
Bob ya ha probado el servidor MCP por nosotros. No obstante, probemos a introducir algunas consultas por nuestra cuenta en la ventana de chat para ver si Bob es capaz de deducir los términos de búsqueda correctos y los parámetros necesarios.
Pregúntele a Bob: "¿Cuáles son los últimos artículos sobre el seguimiento de agentes LLM?"
Por sí solo, Bob extrajo la consulta correcta de nuestra instrucción y añadió algunas palabras clave adicionales para mejorar la búsqueda. Bob también fijó el número máximo de resultados en 10 y clasificó los documentos por relevancia. Genial.
Probemos una consulta más.
Curiosamente, Bob ha ajustado automáticamente la consulta de búsqueda al darse cuenta de que aparecían resultados no deseados. Bob no ejecuta ciegamente llamadas a herramientas, sino que colabora con el usuario como un agente útil. Tras dos rondas de este proceso, Bob nos entregó varios artículos que se ajustan bien a nuestra tarea inicial.
Muchos servidores MCP de código abierto también incluyen documentos para que otros puedan empezar fácilmente. Vamos a pegar esta instrucción en la ventana del chat:
"En este directorio, crea un archivo README.md para documentar este servidor MCP. Incluye instrucciones de configuración y uso."
Con una simple instrucción, Bob creó un documento
¿Quizás le interese crear un agente de IA especializado en investigación con watsonx Orchestrate que pueda acceder a este servidor MCP? Bob puede crear un agente con una sola instrucción. En primer lugar, instale el servidor watsonx Orchestrate ADK prediseñado del mercado que se encuentra en el panel de configuración de MCP que exploramos en el paso 1. Luego, envíe este comando:
"Crea un agente watsonx Orchestrate que utilice este servidor MCP arxiv".
Si tiene el servicio Watsonx Orchestrate en ejecución localmente, Bob ejecutará los comandos necesarios por usted. Si prefiere ejecutar los comandos usted mismo más tarde, Bob escribirá los scripts y documentará los comandos necesarios.
Analicemos cada archivo para entender mejor lo que generó Bob. Aquí está el archivo toolkit-config.yaml
kind: mcp
name: arxiv-toolkit
description: Toolkit for searching arXiv research papers. Proporciona acceso a metadatos en papel, resúmenes e información de publicaciones desde la base de datos arXiv.
package_root: /local/path/to/arxiv-server
language: node
command: node /local/path/to/arxiv-server/arxiv-server/build/index.js
tools:
- "*"
# Made with Bob
Ahora, abramos el archivo research-assistant-agent.yaml
name: research-assistant
kind: native
description: AI research assistant that helps find and summarize academic papers from arXiv. Se especializa en buscar literatura científica, explicar los resultados de la investigación y proporcionar citas.
title: Research Assistant
instructions: |
You are an expert research assistant specializing in academic literature search on arXiv.
## Your Capabilities
- Search arXiv for papers on any scientific topic
- Summarize research findings from abstracts in plain language
- Identify key authors and research trends
- Suggest related papers and topics
- Provide proper citations with arXiv IDs and URLs
## When Responding to Users
1. Always provide arXiv IDs and direct URLs to papers
2. Summarize abstracts in accessible language
3. Highlight key contributions and findings
4. Suggest follow-up searches when relevant
5. Be concise but informative
## Using the search_arxiv Tool
Available parameters:
- query (required): Search query using arXiv syntax
- max_results (optional): 1-50 papers, default 10
- start (optional): Starting index for pagination, default 0
- sort_by (optional): "relevance", "submittedDate", or "lastUpdatedDate"
- sort_order (optional): "ascending" or "descending"
## Advanced Search Syntax
You can use these operators in queries:
- ti:keyword - Search in title
- au:author - Search by author name
- abs:keyword - Search in abstract
- cat:category - Filter by category (e.g., cs.AI, quant-ph, math.CO)
- AND, OR, ANDNOT - Boolean operators
Examples:
- "ti:transformer AND cat:cs.LG" - Transformer papers in machine learning
- "au:Hinton" - Papers by Geoffrey Hinton
- "quantum computing AND cat:quant-ph" - Quantum computing in quantum physics
## Common Categories
- cs.AI - Artificial Intelligence
- cs.LG - Machine Learning
- cs.CL - Computation and Language
- cs.CV - Computer Vision
- quant-ph - Quantum Physics
- math.CO - Combinatorics
- stat.ML - Machine Learning (Statistics)
## Response Format
When presenting papers, use this format:
**"Paper Title"**
- Authors: [Author names]
- Published: [Date]
- Categories: [Categories]
- Summary: [Brief summary of abstract]
- [View paper](arXiv URL)
## Handling Edge Cases
- If no results found: Suggest alternative search terms or broader queries
- If too many results: Recommend narrowing the search with categories or date filters
- If user asks for PDFs: Explain you provide metadata only, but include the URL where they can access the paper
- If unclear query: Ask clarifying questions about the research area or specific interests
tools:
- search_arxiv
config:
hidden: false
enable_cot: true
tags:
- research
- academic
- papers
- arxiv
- literature-search
# Made with Bob
Este archivo YAML configura nuestro asistente de investigación, un agente de IA especializado que agiliza la investigación académica buscando en arXiv, resumiendo artículos y proporcionando citas en un formato estructurado. Se incluyen instrucciones detalladas que guían el comportamiento del agente, desde la sintaxis de las consultas y el uso de las herramientas hasta el formato de las respuestas y la gestión de los casos extremos. Toda esta información se detalla aprovechando la herramienta search_arxivsetup-instructions.md
En este tutorial, utilizamos IBM Bob, un desarrollador de IDE y pares que da prioridad a la IA, para agilizar la integración de MCP para la investigación académica. Ha creado de manera eficiente un servidor MCP escalable capaz de buscar y recuperar documentos del repositorio arXiv.org. Ahora, su solución está lista para su uso en producción, tanto si decide compartirla como código abierto con la comunidad investigadora como si decide implementarla en las aplicaciones de su empresa para mejorar la obtención de conocimientos.
La verdadera magia de IBM Bob radica en su capacidad para transformar tareas de desarrollo complejas en flujos de trabajo intuitivos y basados en instrucciones. Con solo unas pocas entradas estratégicas, Bob acelera la creación de prototipos, reduce el código repetitivo e incluso sugiere optimizaciones, lo que le permite centrarse en la innovación más que en la implementación.
A medida que siga explorando sus capacidades, piense en cómo Bob puede optimizar aún más su servidor MCP. Entre los beneficios podemos enumerar la adición de filtrado avanzado, actualizaciones en tiempo real o integración con otras bases de datos académicas como PubMed o IEEE Xplore. Todas estas posibilidades, y muchas más, son posibles con unas sencillas instrucciones utilizando IBM Bob.
¿Listo para dar el próximo paso? Experimente con la personalización de su servidor MCP o profundice más en las características de Bob para desbloquear aún más potencial de automatización. ¡Feliz codificación!
Cree, implemente y gestione potentes asistentes y agentes de IA que automaticen flujos de trabajo y procesos con IA generativa.
Construya el futuro de su empresa con soluciones de IA en las que puede confiar.
Los servicios de IA de IBM Consulting ayudan a reinventar la forma de trabajar de las empresas usando IA para la transformación.