ai-agent-mcp
Provides keyless web search through DuckDuckGo via the ddgs metasearch library, returning result titles, URLs, and snippets for agent queries.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@ai-agent-mcpSearch for the Model Context Protocol and summarize it in three sentences."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
ai-agent-mcp
A small, free AI agent that answers questions by calling tools over the Model Context Protocol. The language model runs on Groq's free API or on Ollama on your own machine. Web search goes through DuckDuckGo and does not need an API key. The default path does not call a paid service and does not ask for a credit card.
The project is a complete MCP host and server, not a wrapper around a single chat endpoint. Tools live in their own process. The agent discovers them at runtime with tools/list, then calls them with tools/call over stdio. The same server can be attached to any other MCP host.
Features
MCP server, built with the official
mcpPython SDK (v2), speaking stdio.Four tools: keyless web search, a safe calculator, an HTTP fetch with timeouts and size limits, and the current time.
Tool-calling loop that lists those tools, sends their JSON Schemas to the model, executes the requested calls, and stops when the model answers.
Two free model providers, selected with a flag or an environment variable: Groq and local Ollama. Both are used through the OpenAI-compatible chat API.
CLI for a single question, an interactive chat, listing tools, or serving MCP on stdio.
Offline test suite. Network calls and model calls are mocked. Lint and tests run in GitHub Actions.
Related MCP server: veriloop
Quick start
Requires Python 3.11 or newer.
git clone https://github.com/taha080/ai-agent-mcp.git
cd ai-agent-mcp
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
cp .env.example .envPut a Groq key in .env (see below), then:
ai-agent-mcp tools
ai-agent-mcp ask "What is (17 * 23) + sqrt(144)?"
ai-agent-mcp --show-trace ask "Search for the Model Context Protocol and summarize it in three sentences."
ai-agent-mcp chat--show-trace prints each tool call and its result on stderr. The answer stays on stdout, so you can pipe it.
Use Ollama instead of Groq:
ai-agent-mcp --provider ollama --model llama3.2 ask "What time is it in Tokyo?"You can also run the package module directly: python -m ai_agent_mcp ask "2 + 2".
Architecture
The CLI is the host. It owns the conversation and the model. It does not implement search, math, or HTTP itself. Those are tools on an MCP server that the host launches as a child process.
flowchart TD
user[User]
cli[CLI host]
agent[Agent loop]
llm[LLM provider: Groq or Ollama]
client[MCP client over stdio]
server[MCP server]
search[web_search]
calc[calculate]
fetch[fetch_url]
clock[current_time]
user --> cli --> agent
agent <--> llm
agent <--> client
client <-->|"JSON-RPC on stdin and stdout"| server
server --> search
server --> calc
server --> fetch
server --> clockOne question that needs arithmetic looks like this:
sequenceDiagram
participant User
participant Agent
participant LLM
participant Server as MCP server
User->>Agent: What is (17 * 23) + sqrt(144)?
Agent->>Server: tools/list
Server-->>Agent: calculate, web_search, fetch_url, current_time
Agent->>LLM: messages plus tool schemas
LLM-->>Agent: tool call calculate
Agent->>Server: tools/call calculate
Server-->>Agent: 403
Agent->>LLM: tool result
LLM-->>Agent: final answer
Agent-->>User: answerThe loop stops when the model returns a message with no tool calls, or when it hits --max-steps (default 8). Several tool calls in one model response are executed before the next model request. A tool error is sent back as the tool result so the model can correct the arguments. The model is not given a chance to pretend the tool succeeded.
How MCP is used
The server is MCPServer from mcp.server. Each tool is a typed Python function with @mcp.tool(). The SDK builds the JSON Schema from the type hints and the docstring, serves tools/list and tools/call, and speaks the protocol. python -m ai_agent_mcp.server calls mcp.run(), which is the stdio transport: one JSON-RPC message per line on stdin and stdout. Logging goes to stderr so it cannot corrupt the stream.
The agent uses the SDK Client with StdioServerParameters. Entering the client context starts the server subprocess, negotiates the protocol, and closes the process on the way out. The session turns each MCP tool into an OpenAI function definition (name, description, parameters) because that is the tool-calling shape both Groq and Ollama accept. Results come back as MCP content blocks and are flattened to text for the next model turn.
The server publishes short instructions. The client reads client.instructions and appends them to the system prompt, so the model hears the server's own description of the tools rather than a second hard-coded copy.
Because the server is a normal stdio MCP server, another host can use it without this agent. A Claude Desktop or Cursor snippet looks like this (use the Python that has the package installed):
{
"mcpServers": {
"ai-agent-mcp": {
"command": "python",
"args": ["-m", "ai_agent_mcp.server"]
}
}
}Tools
Tool | What it does | What it refuses |
| Arithmetic with | Anything outside that allowlist. The implementation walks an AST. It does not call |
| Text search through the | Empty or very long queries. |
| GET one public | Non-HTTP schemes, |
| Local clock in an IANA timezone, as an ISO-8601 string. No network. | Unknown timezone names. |
fetch_url checks the addresses a hostname resolves to before reading the body. That blocks the common case of a public name pointing at an internal IP. It is not a complete SSRF defense against DNS rebinding within a single request, and it is not a browser.
Configuration
Flags override environment variables. A .env file in the working directory is loaded if present and does not override variables already set in the shell. .env is gitignored. .env.example is the template and contains no secrets.
Variable | Flag | Default | Meaning |
|
|
|
|
|
|
| Groq model id. |
|
|
| Local model name. It needs to support tool calling. |
| empty | Free key from Groq. Required only when the provider is Groq. | |
|
| Override for tests or a proxy. | |
|
| Ollama's OpenAI-compatible base. A URL without | |
|
|
| Model calls per user message. |
|
| Sampling temperature, from 0 to 2. | |
|
| Seconds to wait for one model response. | |
| off | Print tool calls and full results to stderr. The chat command always prints a short preview. |
ai-agent-mcp tools and ai-agent-mcp serve do not need an API key.
Groq
Create a free account at console.groq.com. The free tier does not require a credit card.
Open API keys and create a key.
Copy
.env.exampleto.envand setGROQ_API_KEY. Leave the file untracked.Confirm the model id against the current model list. Free-tier rate limits change;
llama-3.1-8b-instantis the default because it supports tool calling and has a generous daily quota. If a model id is retired, setGROQ_MODELor pass--model.
The client sends Authorization: Bearer ... and never writes the key into the request body, the logs, or the repository.
Ollama
Install Ollama from ollama.com and start it (
ollama serveif it is not already running as a service).Pull a model that can call tools:
ollama pull llama3.2Run the agent with
--provider ollama. No key is read.
Ollama's OpenAI-compatible endpoint is http://127.0.0.1:11434/v1/chat/completions. Tool-calling quality depends on the model. If a local model ignores the tools array, pick another tool-capable model such as a recent Llama 3.1, Llama 3.2, or Qwen 2.5 build.
Usage
# List the tools the server actually exposes.
ai-agent-mcp tools
# One question. Arithmetic should go through calculate, not mental math.
ai-agent-mcp ask "What is (17 * 23) + sqrt(144)?"
# Show the tool trace while researching.
ai-agent-mcp --show-trace ask "What is the Model Context Protocol? Search, then answer in three sentences."
# Interactive session. /tools reprints the tool list. /exit quits.
ai-agent-mcp chat
# Run only the server. A host owns stdin and stdout. This blocks.
python -m ai_agent_mcp.serverIn chat, each user line is one turn. The conversation, including tool results, is kept in memory until you exit. It is not written to disk.
Illustrative trace for the arithmetic question (--show-trace). The final sentence is the model's; the tool result is not.
tool> calculate {"expression": "(17 * 23) + sqrt(144)"}
403
(17 * 23) + sqrt(144) is 403.Development
pip install -e ".[dev]"
python -m ruff check .
python -m ruff format --check .
python -m pytestThe suite is offline:
Calculator tests check ordinary arithmetic and reject imports,
eval, attribute access, huge exponents, and division by zero. A second test parses the calculator module and fails if it contains a call toeval,exec, orcompile.Fetch tests use
httpx.MockTransport. They cover HTML cleaning, plain text, JSON, truncation, HTTP errors, timeouts, non-text bodies, blocked URLs, redirects onto loopback, and a hostname whose fake resolver returns a private address.Search tests pass a fake backend. One test replaces the
DDGSclient with a function that fails the test if it is constructed.The agent loop uses a scripted model and an in-memory session: no tool, one tool, JSON-string arguments, invalid JSON, a tool exception, parallel tool calls, and the step limit.
Provider tests mock HTTP and assert that a failed Groq response does not echo the API key. A missing key fails before any socket is opened.
One test launches the real server as a stdio subprocess, lists the tools, and runs the agent loop with a fake model against
calculate. No model provider is contacted.
GitHub Actions (.github/workflows/ci.yml) runs Ruff and pytest on Python 3.11 and 3.12 for pushes to main and for pull requests.
Project structure
src/ai_agent_mcp/
cli.py argument parsing and the chat / ask commands
config.py environment and .env loading
server.py MCP server and tool registration
agent/
loop.py tool-calling loop
session.py stdio MCP client
llm.py Groq and Ollama chat clients
models.py shared dataclasses and protocols
prompt.py system prompt
tools/
calculator.py AST evaluator
search.py ddgs-backed search
fetch.py guarded HTTP fetch
clock.py current time
tests/ offline pytest suite
.github/workflows/ci.yml Ruff and pytest
.env.example committed template, no secretsTool functions do the work. server.py only adapts them to MCP and turns an expected ToolFailure into an MCP ToolError, which the client reports as is_error with a message the model can read. The loop depends on a small ToolSession protocol, so tests do not start a subprocess unless they are specifically checking stdio.
Design notes
No paid dependency. Groq's free tier or a local Ollama process, plus DuckDuckGo through
ddgs. HTTP useshttpx. HTML parsing uses the standard library.Secrets stay in the environment. The only credential is
GROQ_API_KEY. It is read at startup, sent as a bearer token, and not logged..envis ignored by git;.env.exampleships with an empty value.The calculator is an allowlist. Operators and function names are explicit. Unknown syntax raises before anything runs. Results that are non-finite or absurdly large are rejected.
The fetch tool is bounded. Scheme check, hostname denylist, literal-IP check, DNS check on live requests, redirect check, timeout, redirect cap, and a byte cap. Tests inject the transport and the resolver so none of that requires a network.
The model is replaceable.
LanguageModel.completeis the only method the loop needs. Groq and Ollama share one OpenAI-compatible implementation with different base URLs. Ollama does not receivetool_choice, which some local builds reject.
Roadmap
Serve the same tools over Streamable HTTP so more than one client can attach.
Add a couple more keyless tools: an Open-Meteo weather lookup and a Wikipedia summary.
Keep a transcript on disk between chat sessions.
Add a small eval set that records which tool should run for a fixed list of questions.
Expose the last fetched page as an MCP resource, not only as a tool result.
License
MIT. See LICENSE.
This server cannot be deployed
Maintenance
Related MCP Connectors
MCP server for your apps' tools and custom tools, plus hosted AI agents and approval-gated workflows
AI Reasoning Cache & Consensus Layer with 11 MCP tools via Streamable HTTP.
The OpenRouter for tools. One MCP connection gives any AI agent 254 hosted tools, pay per call.
Hosted MCP runtime where your agent publishes its own tools by tool call and keeps working.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceProvides math and weather tools accessible via LangGraph agent using MCP protocol with stdio and streamable HTTP transports.1-
- AlicenseAqualityDmaintenanceExposes a verified tool registry (calculator, sandboxed file read, web fetch) over MCP stdio, enabling any MCP-capable client to reuse the same tools from the inspectable ReAct loop.3MIT
- AlicenseNot gradedqualityCmaintenanceProvides MCP servers (stdio and HTTP) with tools for calculation, text statistics, and unit conversion, plus an agent host that uses Gemini to orchestrate tool calls across them.ISC
- FlicenseNot gradedqualityCmaintenanceEnables an agent to discover and call local MCP tools over a Streamable HTTP endpoint using Groq for reasoning and tool selection.-