Skip to main content
Glama
ziyakhan04

MCP Tool Server

by ziyakhan04

MCP Tool Server — AI Agent Tool Integration Platform

A small, production-shaped example of how an AI agent can discover and call reusable backend tools through the Model Context Protocol (MCP), with the same business logic also exposed as a conventional REST API — proving that MCP is an additional interface, not a parallel implementation.

Problem Statement

AI agents need a standard way to call backend capabilities (databases, external APIs, calculators, utilities) without every application inventing its own bespoke tool-calling glue. This project demonstrates that pattern end-to-end: a real agent, backed by a real LLM, discovering and invoking real tools against a real database and a real external API — while proving the tools aren't just an AI-only side channel by exposing the identical logic over REST.

Related MCP server: Swagger/Postman MCP Server

What is MCP?

The Model Context Protocol is an open protocol for connecting AI applications to external tools and data sources through a standard client/server interface. An MCP server exposes typed, discoverable tools (and optionally resources/prompts); an MCP client connects to it, lists what's available, and invokes tools with structured arguments, getting structured results back.

The key difference from "just calling a REST API": tool discovery is dynamic and machine-readable. An agent doesn't need hardcoded knowledge of your API's shape — it asks the server what it can do, gets typed schemas back, and an LLM can reason about which tool fits a request. This project's agent (see app/agent/) never hardcodes tool names; it calls list_tools() at runtime.

Why This Project Exists

To demonstrate, concretely and testably:

  1. A clean separation between transport/adapter layers (MCP tools, REST endpoints) and business logic (services)

  2. Zero duplication of logic between the MCP and REST interfaces

  3. A real (not simulated) LLM-driven agent loop doing tool discovery and selection

  4. Production-style error handling, logging, validation, and testing at every layer

Architecture

flowchart TD
    User --> Agent
    Agent --> LLM[LLM Provider - Groq]
    Agent --> MCPClient[MCP Client]
    MCPClient --> MCPServer[FastMCP Server]
    MCPServer --> CalcTool[Calculator Tools]
    MCPServer --> TaskTool[Task Tools]
    MCPServer --> GitHubTool[GitHub Tool]
    MCPServer --> UtilTool[Utility Tool]

    TaskTool --> TaskService[Task Service]
    GitHubTool --> GitHubService[GitHub Service]
    TaskService --> TaskRepo[Task Repository]
    TaskRepo --> SQLite[(SQLite)]
    GitHubService --> GitHubAPI[GitHub Public API]

    RestAPI[FastAPI REST API] --> TaskService
    RestAPI --> GitHubService

MCP tools and FastAPI endpoints both call directly into the same service layer (app/services/). Neither interface contains business logic of its own.

Key Features

  • Calculator tools: add, subtract, multiply, divide — typed, no eval(), clean division-by-zero handling

  • Task management: full CRUD (create_task, list_tasks, get_task, complete_task, delete_task) backed by SQLite, with a repository/service split

  • GitHub tool: get_repository_info(owner, repo) against the public GitHub API, with input validation, timeouts, and clean 404/error handling

  • Utility tool: text_statistics — word/character/sentence counts and average word length

  • REST API: FastAPI endpoints reusing the identical service layer, with OpenAPI docs at /docs

  • AI Agent: connects via MCP, dynamically discovers tools, uses Groq for tool selection, executes via MCP, and never touches the database or GitHub directly

  • Tests: 23+ unit and integration tests covering services, repositories, REST endpoints, and MCP tool invocation

Technology Stack

Layer

Technology

MCP server

FastMCP 2.14

REST API

FastAPI

Validation

Pydantic v2

Persistence

SQLite (stdlib sqlite3, no ORM)

Testing

pytest, pytest-asyncio

LLM (agent tool selection)

Groq (openai/gpt-oss-120b)

Config

pydantic-settings, .env

FastMCP is a third-party framework, not part of this project. Credit: PrefectHQ/fastmcp.

Project Structure

MCP-Tool-Server/ ├── app/ │ ├── main.py # FastAPI entrypoint │ ├── config.py # env-based settings │ ├── logging_config.py │ ├── agent/ # LLM provider + agent loop + CLI │ ├── mcp/ │ │ ├── server.py # FastMCP server, tool registration │ │ └── tools/ # thin MCP adapters │ ├── api/ │ │ └── routes.py # thin REST adapters │ ├── services/ # business logic (shared by MCP + REST) │ ├── repositories/ # SQL, isolated here only │ ├── database/ # connection + schema │ └── schemas/ # Pydantic models ├── tests/ │ ├── unit/ │ └── integration/ ├── docs/ │ └── architecture.md ├── requirements.txt ├── requirements-dev.txt └── .env.example

Installation

git clone <your-repo-url>
cd MCP-Tool-Server
python -m venv .venv
.venv\Scripts\Activate.ps1
pip install -r requirements.txt -r requirements-dev.txt

Environment Configuration

Copy .env.example to .env and fill in your Groq API key (get one free at https://console.groq.com):

DATABASE_URL=sqlite:///./data/app.db GITHUB_API_URL=https://api.github.com LOG_LEVEL=INFO LLM_PROVIDER=groq LLM_API_KEY=your_key_here LLM_MODEL=openai/gpt-oss-120b

.env is gitignored and must never be committed.

Running the MCP Server

python -m app.mcp.server

Starts in stdio transport mode, waiting for an MCP client.

Running the FastAPI REST API

uvicorn app.main:app --reload

Docs at http://127.0.0.1:8000/docs.

Running the AI Agent

python -m app.agent.cli

Example prompts: Calculate 125 / 5. Create a high priority task called Finish Resume. What are the stars and forks of PrefectHQ/fastmcp?

Example Tool Calls (via MCP Client)

async with Client(mcp) as client:
    result = await client.call_tool("add", {"a": 25, "b": 18})
    result = await client.call_tool("create_task", {"title": "Finish Resume", "priority": "high"})
    result = await client.call_tool("get_repository_info", {"owner": "PrefectHQ", "repo": "fastmcp"})

API Examples (REST)

$body = @{ title = "Prepare for interview"; priority = "high" } | ConvertTo-Json
Invoke-RestMethod -Uri http://127.0.0.1:8000/tasks -Method Post -Body $body -ContentType "application/json"

Invoke-RestMethod -Uri http://127.0.0.1:8000/tasks -Method Get
Invoke-RestMethod -Uri "http://127.0.0.1:8000/github/PrefectHQ/fastmcp" -Method Get

Testing

pytest -v

23 tests covering calculator logic, task service CRUD + edge cases, GitHub service against faked HTTP responses (no real network calls in tests), REST endpoint integration, and MCP tool invocation via FastMCP's in-process Client.

Design Decisions

  • No ORM for SQLite: a single-table app doesn't justify SQLAlchemy; hand-written parameterized SQL, isolated entirely inside repositories/, is simpler to reason about and defend.

  • Service layer is the single source of business logic: both MCP tools and REST routes are thin adapters that call the same functions — verified directly by tests that exercise both paths against the same behavior.

  • lru_cached settings: environment variables are read once per process; tests explicitly clear this cache when they need to override config (see tests/conftest.py).

  • Logging to stderr, not stdout: the MCP stdio transport uses stdout for protocol messages; logging there would corrupt the stream.

  • Agent gives a direct, transparent answer rather than a second LLM "explain the result" call: keeps the demo deterministic; a natural-language rephrasing pass is a documented future improvement, not a hidden non-determinism.

Error Handling

Every service raises specific, named exceptions (TaskNotFoundError, RepositoryNotFoundError, GitHubServiceError, ValueError for bad input). FastAPI translates these into structured JSON responses with appropriate status codes (404, 400, 502, 500) via app/main.py's exception handlers — no stack traces are ever returned to a client. On the MCP side, FastMCP converts the same exceptions into ToolErrors that a calling agent must explicitly catch, exactly as demonstrated in app/agent/agent.py.

Security Considerations

  • No secrets in source code; all config via environment variables, .env gitignored

  • No eval() anywhere — calculator tools are plain arithmetic

  • GitHub owner/repo inputs validated against a strict character pattern before being used in a URL

  • All SQL is parameterized; no string-interpolated queries

  • External HTTP calls have explicit timeouts

  • Errors never leak stack traces or internal details to callers

  • LLM-generated tool arguments are validated by the same Pydantic schemas every other caller goes through — the agent does not get a trusted bypass

Future Improvements

  • Migrate SQLite → PostgreSQL for concurrent/multi-process use

  • Containerize with Docker

  • Add a second LLM provider (OpenAI/Gemini) behind the existing LLMProvider abstraction

  • Add a rephrasing pass so the agent's final answer reads naturally rather than stating the raw tool result

  • Add retry/backoff around the GitHub HTTP client

  • Correlation IDs across log lines for request tracing

FastMCP Attribution

Built on FastMCP by PrefectHQ. This project is an independent application using FastMCP as a dependency; it is not a fork of, or affiliated with, FastMCP itself.

License

MIT

Maintenance

ActivityMaintained
ResponsivenessNo issues

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    D
    maintenance
    A lightweight, modular API service that provides useful tools like weather, date/time, calculator, search, email, and task management through a RESTful interface, designed for integration with AI agents and automated workflows.
    5
    1
    MIT
  • F
    license
    Not graded
    quality
    D
    maintenance
    Server that ingests Swagger/OpenAPI specifications and Postman collections, providing just 4 strategic tools that allow AI agents to dynamically discover and interact with APIs instead of generating hundreds of individual tools.
    3
    -
  • F
    license
    Not graded
    quality
    D
    maintenance
    Flask-based server that exposes callable tools via HTTP endpoints for AI agents like Gemini CLI, enabling agent orchestration, tool introspection, and workflow automation with a centralized tool registry.
    -