Portfolio MCP Server
Query Ayush's AI project portfolio from any MCP client through 5 structured-data tools.
list_projects— compact summary of all 9 projects (name, one-line description, stack).get_project_details(project_name)— full description, stack, GitHub repo, live demo, and writeup link for one project; case-insensitive partial match (e.g. 'sales' matches 'SalesAgent').search_projects_by_stack(technology)— find projects using a given tech (e.g. LangGraph, Groq, FastAPI, React); case-insensitive, one technology per call.get_flagship_project— the single best project to look at first.get_resume_summary— background, education, target role, core stack, and career highlights.
Runs over stdio for local clients (Claude Desktop, Cursor, custom agents) and installs via pip install portfolio-mcp-server. Limitations: data is static JSON (no live sync), no HTTP/SSE transport, and stack search can't match multiple technologies at once.
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., "@Portfolio MCP ServerWhat projects has Ayush built with FastAPI?"
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.
Portfolio MCP Server
An MCP server that turns my AI project portfolio into something you can query, not just read.
Point any MCP client (Claude Desktop, Cursor, custom agents) at it and ask "What has Ayush built with LangGraph?" or "What's his flagship project?" — it answers from live structured data, not a static PDF.
TL;DR
📦 Published, not just built — live on PyPI and the official MCP registry;
pip install portfolio-mcp-servergets it running in any MCP client in under a minute, no repo clone required.🔧 5 real tools — list, detail-lookup, stack search, flagship pick, and resume summary, all backed by structured data instead of a static README scroll.
✅ CI-tested on every push — lint, type-check, and a real stdio smoke test that calls all 5 tools and validates the JSON schema of each response.
Table of contents
Related MCP server: toad-mcp-server
Why this exists
Most AI-developer portfolios are a list of links. This is a working MCP server — the same protocol agentic products use to connect to tools — built around my own portfolio. It's both a real implementation of the spec and an answer to "show me you've actually built with MCP," not just talked about it.
Demo
MCP Inspector — tool discovery | Live chat demo |
|
|
https://github.com/user-attachments/assets/4c1b844a-087f-48a6-b156-bdef27282acc
Setup → tool calls → live answers, end to end.
Tools exposed
Tool | Description |
| Short summary of all 9 projects |
| Full details for one project |
| Find projects using a given technology |
| The single best project to look at first |
| Background, target role, and core stack |
Quickstart
Option A — install from PyPI (fastest):
pip install portfolio-mcp-serverOption B — clone and run from source (for local edits/testing):
git clone https://github.com/ayush-s-tomar/portfolio-mcp-server.git
cd portfolio-mcp-server
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install -r requirements.txtTest it interactively with the MCP Inspector before wiring it into a client:
mcp dev server.pyThis opens a browser UI where you can call each tool manually and inspect raw request/response payloads.
Connect to Claude Desktop
Open your Claude Desktop config file:
OS | Path |
macOS |
|
Windows |
|
If the file already has an mcpServers key with other servers in it, add
the "portfolio" entry inside the existing object rather than overwriting
the file.
If you installed via PyPI (Option A above):
{
"mcpServers": {
"portfolio": {
"command": "portfolio-mcp-server"
}
}
}If you're running from a cloned source checkout (Option B above): use the absolute path to server.py on your machine:
{
"mcpServers": {
"portfolio": {
"command": "python",
"args": ["/absolute/path/to/portfolio-mcp-server/server.py"]
}
}
}Restart Claude Desktop, then ask it something like:
"What projects has Ayush built with FastAPI?"
Claude will call search_projects_by_stack and answer from the live data.
Stack
Python 3.10+
MCP Python SDK (
FastMCP)stdio transport
Packaged for PyPI and registered on the official MCP server registry (
io.github.ayush-s-tomar/portfolio-mcp-server)
Testing & CI
Every push and pull request runs through GitHub Actions:
Lint —
ruff check .Type check —
mypy server.pySmoke test — spins up the server and calls each of the 5 tools over stdio to confirm they return valid, schema-matching JSON
See .github/workflows/ci.yml. Run the same
checks locally before opening a PR:
pip install -r requirements-dev.txt
ruff check .
mypy server.py
pytestProject structure
portfolio-mcp-server/
├── server.py # FastMCP server + tool definitions
├── data/
│ └── projects.json # Project data the tools read from
├── tests/
│ └── test_tools.py # Smoke tests for each tool
├── requirements.txt
├── requirements-dev.txt
├── pyproject.toml # PyPI packaging config
├── server.json # MCP registry manifest
└── .github/workflows/ci.ymlKnown limitations
Static project data — tools read from
data/projects.json, so adding or updating a project means editing that file and republishing, not a live sync with the actual GitHub repos or portfolio site (see Roadmap — a refresh endpoint isn't built yet).stdio transport only — works great for local MCP clients like Claude Desktop that can spawn the process directly, but there's no HTTP/SSE option yet for a client that needs to reach it remotely over the network.
search_projects_by_stackmatches one technology at a time — asking for projects using both LangGraph and FastAPI together isn't supported yet; each call filters on a single technology.
Roadmap
Publish to PyPI as an installable package
Publish to the official MCP server registry
search_projects_by_stack— support matching on multiple technologies at onceAdd an HTTP/SSE transport option alongside stdio for remote clients
Cache resume/project data with a lightweight refresh endpoint instead of static JSON
License
Released under the MIT License.
Author
Ayush Singh Tomar — GitHub · LinkedIn · Portfolio
If this was useful as a reference for building your own MCP server, a ⭐ on the repo is appreciated.
mcp-name: io.github.ayush-s-tomar/portfolio-mcp-server
Available Tools
5 toolsget_flagship_projectB
Get Ayush's flagship/best project — the one to look at first for a quick sense of his skill level.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden of behavioral disclosure. It only says 'Get' which implies a read operation, but it doesn't mention what happens if no flagship project exists, whether it returns a summary or full details, or any side effects. For a simple read tool this is minimal but still lacking.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, well-structured sentence that front-loads the action and resource, then adds context. Every word is useful and there is no redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is simple with no parameters and no output schema. The description explains the purpose and what it returns (the flagship project), but doesn't clarify the return format or any error conditions. Given the simplicity, it's adequate but not exhaustive.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There are 0 parameters, so the description adds no parameter-specific meaning, which is appropriate. The baseline for 0 parameters is 4, and the description doesn't need to elaborate on any inputs.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'Get' and the resource 'Ayush's flagship/best project', and adds the purpose ('the one to look at first for a quick sense of his skill level'). It distinguishes itself implicitly from siblings like list_projects and get_project_details by focusing on a single, curated project, but doesn't name them explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies when to use it: when you want a quick sense of skill level. It doesn't explicitly state alternatives or when not to use it, but the purpose is reasonably clear. No exclusions or comparisons to siblings are given.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_project_detailsA
Get full details for a single project by name (case-insensitive, partial match allowed, e.g. 'sales' matches 'SalesAgent').
Returns description, full stack, GitHub repo, live demo link, and writeup link if one exists.
| Name | Required | Description | Default |
|---|---|---|---|
| project_name | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It discloses the matching semantics (case-insensitive, partial) and lists the exact return fields (description, full stack, GitHub repo, live demo link, writeup link if exists). It does not mention error handling or whether a missing project returns null, but for a read-only get operation the disclosed behavior is reasonably transparent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences with no filler. The purpose and matching behavior are front-loaded, and the return fields are listed efficiently. Every sentence adds value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter read tool with no output schema, the description covers the essential context: matching rules and return content. It omits edge cases (e.g., no match behavior) but that is minor given the simplicity and the fact that the parameter is well-explained. It is sufficiently complete for an agent to invoke correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0% and the schema only says 'project_name' is a string. The description fully compensates by explaining the parameter's semantics: case-insensitive, partial match allowed, with a concrete example ('sales' matches 'SalesAgent'). This adds substantial meaning beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Get') and resource ('full details for a single project'), and clarifies the lookup method (by name, case-insensitive, partial match) with a concrete example. This clearly distinguishes it from sibling tools like list_projects and search_projects_by_stack, which serve different lookup purposes.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage when you need full details for a known project name, and the matching behavior (case-insensitive, partial) suggests when it applies. However, it does not explicitly contrast with siblings or state when to use an alternative, such as list_projects for browsing or search_projects_by_stack for filtering by stack. No exclusion or alternative is mentioned.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_resume_summaryA
Get a summary of Ayush's background: education, target role, core tech stack, and career highlights.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of disclosing behavioral traits. It only says 'Get a summary,' which implies a read operation, but it does not explicitly state that the tool has no side effects, does not require special permissions, or what the response format might be. There is no mention of data freshness, caching, or failure modes, leaving agents to assume the obvious.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, well-structured sentence with a colon followed by a concise list of the summary's components. It is front-loaded with the action and resource, contains no redundant words, and every phrase adds value. This is an exemplary level of conciseness.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a no-parameter, read-only tool, the description covers the essential information: what it returns and its scope. It does not describe the output format, but since there is no output schema, the agent may need to infer that a summary could be text or structured. Still, the tool is simple enough that this is a minor gap rather than a critical omission.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters and the input schema is an empty object, so schema description coverage is trivially 100%. The baseline for 0-parameter tools is 4, and the description adds no parameter-specific meaning because none is needed. It appropriately focuses on the summary's content rather than inputs.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's action ('Get a summary') and its specific resource (Ayush's background), enumerating the exact content categories (education, target role, core tech stack, career highlights). This makes it easily distinguishable from siblings like list_projects and get_project_details, which are project-focused.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No explicit guidance is provided about when to use this tool versus alternatives. While the sibling tools are clearly project-related and this is the only resume-summary tool, the description does not state any conditions, exclusions, or mention that for detailed project info one should use a sibling tool. Usage is only implied by the tool's name and purpose.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_projectsA
List all projects in Ayush's portfolio with a short summary of each.
Returns a compact list (name, one-line description, stack) — use get_project_details for the full description, GitHub link, and demo URL.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the burden of explaining behavior. It discloses that the result is a compact list containing name, one-line description, and stack, and that it intentionally omits full details. This is adequate for a simple read-only enumeration with no parameters.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences with no filler. The primary purpose is stated first, followed by useful return-shape information and a sibling alternative, making it easy to parse.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a no-argument listing tool with an output schema, the description is complete: it defines the result shape, notes the intentional limitation, and names the sibling tool for deeper data. Nothing needed for correct invocation is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so the schema fully covers everything. The 0-parameter baseline of 4 applies; no parameter explanation is needed.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb and resource: 'List all projects in Ayush's portfolio'. It also distinguishes itself from the most similar sibling by saying it returns a compact list, while get_project_details provides full details.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly states when to use this tool: when a compact overview of all projects is needed. It explicitly routes users to get_project_details for full descriptions, GitHub links, and demo URLs, though it does not mention when search_projects_by_stack or get_flagship_project would be more appropriate.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_projects_by_stackA
Find all projects that use a given technology or tool, e.g. 'LangGraph', 'Groq', 'FastAPI', 'React'. Case-insensitive, partial match.
Useful for answering "does Ayush have experience with X?"
| Name | Required | Description | Default |
|---|---|---|---|
| technology | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It discloses key behavior: case-insensitive matching and partial matching. 'Find' also implies a read-only search operation)Skip. It could add more about limits or error behavior, but for a simple search tool the essential behavior is covered.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded. The first sentence states the action and scope, examples come immediately after, and the useful query-context sentence earns its place without redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter search tool, the description covers matching behavior and intended use. An output schema exists, so return-value documentation is not required. It could more explicitly state the search scope (e.g., all of Ayush's projects), but the usage hint makes this reasonably clear.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must define the parameter. It does so thoroughly: 'technology' is explained as a technology or tool, with concrete examples and additional matching semantics (case-insensitive, partial match). This exceeds the bare type/title in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Find all projects that use a given technology or tool.' It includes concrete examples and clearly distinguishes this from sibling tools like list_projects by emphasizing stack-based filtering.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives a concrete use case: answering 'does Ayush have experience with X?' This clearly communicates when to invoke the tool. It does not explicitly name alternatives or state when not to use it, but the intended context is evident.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
5 tool updates
v1.0.1- First observed
get_flagship_project - First observed
get_project_details - First observed
get_resume_summary - First observed
list_projects - First observed
search_projects_by_stack
TDQS
Scored across 5 tools
Each tool has a clearly distinct purpose: listing projects, getting details, searching by stack, retrieving the flagship project, and summarizing resume background. No two tools appear to overlap in ways that would cause misselection.
All tool names follow a consistent verb_noun pattern using list_, get_, or search_ prefixes. The naming is predictable and makes the toolset easy to navigate.
Five tools is well-scoped for a portfolio server. Each tool covers a meaningful query a user or agent would need, without unnecessary redundancy or bloat.
The toolset covers the full read-only portfolio domain: browsing projects, retrieving full details, filtering by technology, identifying the best project, and accessing background information. There are no obvious dead ends or missing critical operations.
Maintenance
Related MCP Connectors
MCP server for generating rough-draft project plans from natural-language prompts.
Nifty's MCP server — exposes tasks, projects, messages, and files as tools for AI agents.
- UnifAPIOAuthcom.unifapi
Hosted MCP server for live public-data APIs and Skills for AI agents.
Capability registry for the agentic economy. Semantic search over verified MCP server listings.
Related MCP Servers
- AlicenseAqualityDmaintenanceAn MCP server that lets recruiters and AI assistants explore your profile, skills, and projects through natural language.6MIT
- FlicenseAqualityDmaintenanceMCP server exposing portfolio AI tools including semantic search, evaluation framework, and prompt management, enabling natural language interaction with these services via Claude Desktop.5-
- FlicenseNot gradedqualityDmaintenanceAn MCP server for controlling the TimeLiner project management system, enabling AI clients to manage projects, tasks, members, and more via natural language.-
- FlicenseNot gradedqualityBmaintenanceAn MCP server that enables AI assistants to interact with OpenProject, listing projects and work packages and managing resources through natural language.-

