A learning repository demonstrating MCP (Model Context Protocol) implementations across multiple lessons with increasing complexity
This is a learning/tutorial repository with 5 tools spread across 4 lessons. While tool definitions are visible and basic input schemas exist, the server exhibits significant quality gaps: duplicate tool definitions (two 'add' tools), minimal descriptions (10-50 chars, well below the 194-char baseline), and no documented output schemas. Descriptions lack context on WHEN to use each tool or WHAT it returns. Parameters have types but descriptions are trivial. Error handling is absent from visible code. No pagination support for the SQL tool despite returning potentially large result sets. This is typical of a learning/prototype codebase, not production-ready.
Add two numbers
Add two numbers
Execute a SQL query on the chinook database.
Get the complete schema of the chinook database.
Multiply two numbers
Duplicate tool names: two distinct 'add' tools defined (lesson-1/client.py and lesson-2/server.py). LLMs cannot disambiguate between them, they will select arbitrarily or fail.
Tool descriptions are extremely short (10-50 characters) and lack context. 'Add two numbers' does not explain WHEN to use this tool vs a calculator, WHAT the output type is, or any prerequisites. Baseline is 194 chars.
No documented output schemas for any tool. LLMs cannot plan downstream steps without knowing the structure of returned data. E.g., does 'execute_sql' return a string, an array, an object? Markdown table as string is lossy.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | F | 49 | 2026-07-28+ | v2 |
| 2026-03-09 | F | 40 | - | v1 |
execute_sql tool accepts arbitrary SQL queries without input validation, sanitization, or constraints. This is a SQL injection and data destruction vector. LLMs can be tricked into passing malicious queries.
execute_sql returns results as a single markdown string with no pagination, limit, or offset parameters. Large result sets will blow the LLM context window without explicit result capping.
No error handling guidance. The code catches sqlite3.Error and returns a string, but does not categorize errors as retryable, user-fixable, or fatal. An LLM cannot decide what to do next.
Parameter descriptions are missing or trivial. The 'query' parameter in execute_sql has description 'The SQL query to execute' but does not specify format constraints, allowed operations (SELECT only? DML?), or examples.