Skip to main content
Glama
ayush-s-tomar

Portfolio MCP Server

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.

License: MIT Python 3.10+ PyPI MCP CI Code style: ruff PRs Welcome

TL;DR

  • 📦 Published, not just built — live on PyPI and the official MCP registry; pip install portfolio-mcp-server gets 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

MCP Inspector Demo

MCP 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

list_projects

Short summary of all 9 projects

get_project_details(project_name)

Full details for one project

search_projects_by_stack(technology)

Find projects using a given technology

get_flagship_project

The single best project to look at first

get_resume_summary

Background, target role, and core stack

Quickstart

Option A — install from PyPI (fastest):

pip install portfolio-mcp-server

Option 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.txt

Test it interactively with the MCP Inspector before wiring it into a client:

mcp dev server.py

This 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

~/Library/Application Support/Claude/claude_desktop_config.json

Windows

%APPDATA%\Claude\claude_desktop_config.json

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.py

  • Smoke 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
pytest

Project 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.yml

Known 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_stack matches 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 once

  • Add 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 tools
get_flagship_projectB

Get Ayush's flagship/best project — the one to look at first for a quick sense of his skill level.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

B3.4/5.0
Behavior2/5

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.

Conciseness5/5

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.

Completeness3/5

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.

Parameters4/5

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.

Purpose4/5

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.

Usage Guidelines3/5

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
project_nameYes

TDQS

A4.3/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines3/5

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.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A3.6/5.0
Behavior2/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines2/5

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.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.5/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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?"

ParametersJSON Schema
NameRequiredDescriptionDefault
technologyYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.5/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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.

  1. 5 tool updatesv1.0.1
    • First observedget_flagship_project
    • First observedget_project_details
    • First observedget_resume_summary
    • First observedlist_projects
    • First observedsearch_projects_by_stack

TDQS

A4.2/5.0

Scored across 5 tools

Disambiguation5/5

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.

Naming Consistency5/5

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.

Tool Count5/5

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.

Completeness5/5

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

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers