Notes MCP
MCP Eval Demo
Un ejemplo práctico de cómo usar evaluaciones para verificar que un agente de LLM realmente puede usar de forma eficaz un servidor MCP — no solo que el código del servidor es correcto.
Las pruebas unitarias responden a «¿delete_note borra una nota?». No pueden responder a las preguntas que deciden si un servidor MCP es bueno en la práctica:
¿Encuentra el agente la nota correcta cuando el usuario la describe con palabras en lugar de por id?
¿Se da cuenta de que una vista previa del listado estaba truncada, o responde a partir de media nota?
¿Se da cuenta de que
update_notesobrescribe, o destruye en silencio el contenido del usuario cuando le pide “añade una línea a mi lista de la compra”?¿Se recupera de un mensaje de error o se rinde?
Esas son propiedades de la superficie de las herramientas — nombres, descripciones, esquemas, formas de los resultados, texto de error — y la única manera de comprobarlas es ejecutar un agente real contra el servidor y evaluar lo que ha hecho. Para eso está este repositorio.
Estado
El servidor MCP, su infraestructura y el harness de evaluación ya están en su sitio.
Related MCP server: MCP Notepad Server
El servidor bajo prueba: Notes MCP
Un cuaderno en memoria. El estado reside en el proceso del servidor y se descarta al salir, por lo que cada ejecución de evaluación parte del mismo corpus conocido (consulta seed.py).
Herramienta | Comportamiento | Qué hace |
| escritura | Crea una nota; los títulos deben ser únicos sin distinguir entre mayúsculas y minúsculas. |
| solo lectura | Devuelve el contenido completo de una nota, por id. |
| solo lectura | Lista las notas de la más reciente a la más antigua, como vistas previas truncadas, con un |
| destructivo | Sobrescribe el título y/o el contenido de una nota. |
| destructivo | Elimina una nota de forma permanente. |
Hay varias decisiones de diseño pensadas expresamente para que las evaluaciones tengan algo que detectar:
Ids, no títulos. Toda herramienta de mutación toma un
note_id, así que un agente al que se le pide cambiar “mi lista de la compra” debe buscar el id antes. Ahí es donde los agentes suelen tomar la solución.Vistas previas truncadas.
list_notesdevuelve solo los primeros 120 caracteres de cada nota, marcadas concontent_truncatedycontent_length. Un agente que responde una pregunta de contenido directamente desde un listado falla; un buen agente llama aget_note.Reemplaza, no añade.
update_notesobrescribe. “Añade huevos a mi lista de la compra” es, por tanto, una operación de lectura-modificación-escritura, y un agente que se salta la lectura destruye datos.Errores que enseñan. Cada fallo nombra el valor problemático y señala la herramienta que lo resolvería, de modo que el agente tiene una salida y no un punto muerto.
Estructura
src/notes_mcp/
models.py Pydantic models — also the tool input/output schemas the agent sees
store.py In-memory storage and its error types
seed.py Fixed corpus: stable ids and timestamps, so evals are reproducible
server.py MCP tool definitions, descriptions, and annotations
cli.py `notes-mcp` entry point
evals/
agent.py Builds the pydantic-ai agent under test + local trace capture
task.py One agent turn against a freshly seeded server — the thing evaluated
evaluators.py Custom pydantic-evals evaluators (tool-not-called, argument-contains)
cases.yaml The dataset itself: cases that probe specific MCP misuse patterns
cases.py Loads cases.yaml — registers the custom evaluators, picks the judge model
__main__.py `python -m evals` — runs the dataset against a live model
tests/
test_store.py Unit tests for the storage layer
test_server.py Protocol-level tests through a real MCP client session
scripts/
lint.sh Ruff + pyright + format check
test.sh Unit + protocol tests (fast, free)
evals.sh Agent-behaviour evals against a live model (slow, costs money)Las descripciones de herramientas son constantes a nivel de módulo en server.py, no docstrings en línea. La redacción de las descripciones es lo que principalmente ajustas cuando una evaluación falla, y tenerla en un solo lugar hace que esos cambios sean legibles.
Primeros pasos
Requiere uv y Python 3.12 (fijado en .python-version).
uv sync # create .venv and install everything
uv run scripts/test.sh # unit + protocol tests
uv run scripts/lint.sh # ruff check, pyright (strict), format check
uv run pre-commit install # optional: run the same checks on commitEjecutar el servidor
uv run notes-mcp # stdio, seeded with the sample notes
uv run notes-mcp --empty # stdio, no notes
uv run notes-mcp --transport streamable-http.mcp.json registra el servidor stdio para este proyecto, por lo que un anfitrión MCP que se cualйтесь desde este directorio — Claude Code, por ejemplo — reconoce automáticamente el servidor notes y puedes trabajarlo a mano.
Para leer la superficie de herramientas que vería un agente — que es de lo que realmente va estas evaluaciones — sin iniciar un agente:
uv run fastmcp list .mcp.json # names, signatures, descriptions
uv run fastmcp list .mcp.json --input-schema # ...with the full JSON schemas
npx @modelcontextprotocol/inspector uv run notes-mcp # MCP Inspector, for clicking aroundAcerca de la versión de
mcp: el servidor está construido sobre la biblioteca independiente FastMCP y no con la copia que antes se incluía dentro del SDK demcpcomomcp.server.fastmcp» — mcp 2.0 eliminó ese módulo. FastMCP decide qué versión demcpnecesita (3.x resuelve mcp 1.x), por lo que [pyproject.toml](pyproject.toml) no tiene una dependenciamcpescrita a mano. El harness de evaluación llega a la misma biblioteca desde el otro lado: el cliente MCP depydantic-aise basa enClient` de FastMCP. Así, las dos mitades de este repositorio concuerdan en la versión por construcción y no por un pin que alguien tenga que mantener. FastMCP 4 es el paso que mueve ambas a mcp 2.x, lo que explica por qué la dependencia está limitada por debajo.
Enfoque de pruebas
Dos capas de pruebas, ejecutadas por scripts/test.sh:
test_store.pycubre la semántica del almacenamiento: singularidad, orden de clasificación, límites y marcas de tiempo. Rápidas, exhaustivas, sin protocolo.test_server.pyacciona el servidor en una sesión de cliente MCP entre procesos (fastmcp.Clientsobre el transporte de memoria de FastMCP), por lo que verifica lo que el agente realmente recibe: la lista de herramientas, esquemas JSON, anotaciones de comportamiento, resultados estructurados y texto de error. El protocolo es real; solo lo son el subproceso y el socket.
Las pruebas asíncronas usan el plugin anyio en lugar de pytest-asyncio, porque el cliente del MCP mantiene un cancel scope abierto durante toda vida de la sesión y anyio ejecute la configuración y desmontaje de los fixtures en la misma tarea.
Un tercer tipo de verificación — las evaluaciones del comportamiento del agente — invoca un modelo real y cuesta dinero, así que no forma parte de la suite de pruebas en absoluto; tiene su propio ejecutor y su propio script, descrito a continuación.
El harness de evaluación
evals/ crea un agente pydantic-ai mínimo — un prompt de sistema genérico de una solo línea, agentes few-shot, sin instrucciones tratadas especialmente — y conecta sus únicas herramientas a través de un servidor Notes MCP en proceso mediante pydantic_ai.mcp.MCPToolset (agent.py). El prompt del sistema es deliberadamente escueto: estas evaluaciones existen para comprobar si los propios nombres, descripciones y esquemas del servidor son suficientes para guiar el comportamiento correcto, y no si la ingeniería de prompts puede cubrir una herramienta débil.
evals/ está en el nivel superior y no bajo src/: es una herramienta de desarrollo para este repositorio, no parte del paquete notes-mcp que cualquiera instalaría.
pydantic_evals ejecuta ese agente sobre un Dataset de Case, cada uno dirigido a uno de los cuatro comportamientos el comienzo de este documento:
Caso | Qué comprueba |
| Al pedirle que elimine “mi nota de la lista de la compra”, el agente llama a |
| Una pregunta cuya respuesta se ha truncado en la vista previa de |
| “Añade crackers a mi lista de la compra” debe leer primero la nota completa; la llamada a |
| Al crear una nota con un título que ya existe, no debe desaparecer en silencio el contenido de la nueva nota ni afirmar que se ha creado un duplicado. |
| Una petición para eliminar una nota inexistente no debe dar lugar a una llamada |
| Un camino feliz para comprobación. |
Los casos están en cases.yaml, non en Python — son datos, por lo que añadir un caso o reformular una rúbrica no toca el código. cases.py es solo el cargador: pasa los evaluadores personalizados a Dataset.from_file (un archivo YAML solo puede nombrar un evaluador que el cargador registro) y establece el modelo juez. La cabecera yaml-language-server de el YAML apunta a cases_schema.json, para que un editor pueda completar y validar los nombres de los evaluadores y sus argumentos; hazlo notar sim registro después de añadir o cambiar un evaluador personalizado:
uv run python -c "from evals.cases import write_json_schema; print(write_json_schema())"Los evaluadores combinan las utilidades incorporadas de pydantic-evals (ToolCorrectness, Contains, MaxToolCalls, LLMJudge para los dos casos con más de una recuperación válida) con dos pequeñas personalizadas en evaluators.py: ToolNotCalled (comprueba que una herramienta no se ha invocado más nunca — no existe ToolNotCalled root check) y ArgumentContains (comprobaciones de subcadenas sobre un argumento de herramienta, para los casos de “el contenido antiguo debe conservarse” donde no puede fijarse la redacción exacta de un LLM con un matching de igualdad ni de subdiccionario).sim Contains. Ambos, como los incorporados, leen las pistas de las llamadas a herramientas que captura la combinación de Agent.instrument_all()y una configuración local delogfire.configure() (send_to_logfire=False); consulta configure_instrumentation()` en agent.py.
__main__.py ejecuta el conjunto de datos, imprime un informe completo y sale non-zero si algo fall y ha sido un error de tarea, un evaluador roto o una aserción fallida. La ejecución así:
uv run scripts/evals.shConfigurar un proveedor
NOTES_MCP_EVAL_MODEL selecciona a la vez el proveedor y el modelo, como cadena números:modelo, y su valor predeterminado es anthropic:claude-haiku-4-5-20251001. Copia example a .env y rellena la sección de cualquiera de estos tres que vayas a usar; scripts/evals.sh carga .env automáticamente (a través de python-dotenv; nunca modifica una variable ya definida en tu shell) y .env está en el .gitignore.
Anthropic API (por defecto) — necesita
ANTHROPIC_API_KEY.OpenAI —
NOTES_MCP_EVAL_MODEL=openai:gpt-5yOPENAI_API_KEY.Amazon Bedrock —
NOTES_MCP_EVAL_MODEL=bedrock:<bedrock-model-id>. La autenticación se realiza por la cadena normal de credenciales deboto3, así que no hay nada específicambre específica que configurar más allá de las variables estándar del SDK de AWS: estableceAWS_PROFILEpara usarlo perfil concretado (AWS_DEFAULT_REGIONtambién si este perfil no define una región; nota que debe serAWS_AWS_DEFAULT_REGION, no noAWS_REGION, que la resolución de región de boto3 no comprueba), o déjalos si está definidos en tu valores/región por defecto.
. Igualmente, no hay código el mismo modelo del proveedor: la cadena de eval_model() se pasa directamente al agente y al LLMJudge, y el infer_model de pydantic-ai resuelve el cliente y las credenciales en función del prefijo de uso que vea.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- -licenseNot gradedqualityNot gradedmaintenanceA simple notes system that allows creating, storing, and accessing text notes through MCP resources and tools, with built-in prompt support for generating summaries of stored notes.
- FlicenseBqualityDmaintenanceA learning-focused MCP server that demonstrates core MCP concepts through a simple notepad application, enabling users to create, update, delete, and search notes while exploring tools, resources, and prompts functionality.4
- FlicenseNot gradedqualityDmaintenanceProvides MCP tools to create and retrieve notes stored in memory.
- FlicenseAqualityDmaintenanceA minimal MCP server demonstrating tools, resources, and prompts for managing notes, with a simple notes app that supports adding, listing, deleting notes and summarizing them.31
Related MCP Connectors
Cross-session, cross-device memory for your agent: remember and recall notes. No key to start.
Shared, governed long-term memory for AI agents across tools and sessions via MCP and REST.
AI access to your aNotepad online notes: read, search, write, and organize via 22 tools.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/jasongilman/mcp-eval-demo'
If you have feedback or need assistance with the MCP directory API, please join our Discord server