opensrc-mcp
Supports cloning and managing source code from Git-based repositories for querying and context-efficient batch operations.
Provides capabilities to fetch and query source code directly from GitHub repositories by owner, repo, and specific Git refs.
Facilitates fetching, reading, and searching through source code for JavaScript and TypeScript packages and their dependencies.
Allows fetching, searching, and querying source code from the npm registry, enabling context-efficient analysis of Node.js dependencies.
Enables fetching and searching Python package source code from the Python Package Index (PyPI) for server-side querying and analysis.
Allows for the retrieval and exploration of Python dependency source code through PyPI and pip-compatible sources.
Supports fetching and searching source code for Rust crates from the crates.io registry.
Click on "Install 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., "@opensrc-mcpfetch the zod package and search for where parse is defined"
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.
opensrc-mcp
A codemode MCP server for fetching and querying dependency source code.
Why?
Traditional MCP exposes tools directly to LLMs. This server uses the codemode pattern: agents write JavaScript that executes server-side, and only results return. Benefits:
Context efficient - Large source trees stay server-side
Batch operations - One call to search/read multiple files
LLMs are better at code - More training data for JS than tool-calling
Related MCP server: Satori
Installation
npm install -g opensrc-mcp
# or
npx opensrc-mcpOpenCode Configuration
Add to your OpenCode config (~/.config/opencode/config.json or project opencode.json):
{
"mcp": {
"opensrc": {
"type": "local",
"command": "npx",
"args": ["-y", "opensrc-mcp"]
}
}
}Tool
execute
Single tool exposing all operations. Agents write JS that runs server-side; only results return.
// Available in sandbox:
declare const opensrc: {
// Read operations
list(): Source[];
has(name: string, version?: string): boolean;
get(name: string): Source | undefined;
files(sourceName: string, glob?: string): Promise<FileEntry[]>;
tree(sourceName: string, options?: { depth?: number }): Promise<TreeNode>;
grep(pattern: string, options?: {
sources?: string[];
include?: string;
maxResults?: number;
}): Promise<GrepResult[]>;
astGrep(sourceName: string, pattern: string, options?: {
glob?: string;
lang?: string | string[];
limit?: number;
}): Promise<AstGrepMatch[]>;
read(sourceName: string, filePath: string): Promise<string>;
readMany(sourceName: string, paths: string[]): Promise<Record<string, string>>;
resolve(spec: string): Promise<ParsedSpec>;
// Mutation operations
fetch(specs: string | string[], options?: { modify?: boolean }): Promise<FetchedSource[]>;
remove(names: string[]): Promise<RemoveResult>;
clean(options?: {
packages?: boolean;
repos?: boolean;
npm?: boolean;
pypi?: boolean;
crates?: boolean;
}): Promise<RemoveResult>;
};
declare const sources: Source[]; // All fetched sources
declare const cwd: string; // Project directoryExamples:
// List all fetched sources
async () => opensrc.list()
// Fetch npm package (auto-detects version from lockfile)
async () => opensrc.fetch("zod")
// Fetch multiple packages
async () => opensrc.fetch(["zod", "drizzle-orm", "hono"])
// Fetch GitHub repo at specific ref
async () => opensrc.fetch("vercel/ai@v3.0.0")
// Fetch from other registries
async () => opensrc.fetch("pypi:requests")
async () => opensrc.fetch("crates:serde")
// Get directory tree
async () => opensrc.tree("zod", { depth: 2 })
// Find TypeScript files
async () => opensrc.files("zod", "**/*.ts")
// Text search
async () => opensrc.grep("parse", { sources: ["zod"], include: "*.ts" })
// AST search (structural pattern matching)
async () => opensrc.astGrep("zod", "function $NAME($$$ARGS)", { glob: "**/*.ts" })
// Read a specific file
async () => opensrc.read("zod", "src/index.ts")
// Read multiple files (supports globs)
async () => opensrc.readMany("zod", ["src/index.ts", "packages/*/package.json"])
// Remove a source
async () => opensrc.remove(["zod"])
// Clean all npm packages
async () => opensrc.clean({ npm: true })Package Formats
Format | Example | Description |
|
| npm (auto-detects version) |
|
| npm specific version |
|
| explicit npm |
|
| Python/PyPI |
|
| alias for pypi |
|
| Rust/crates.io |
|
| alias for crates |
|
| GitHub repo |
|
| GitHub at ref |
|
| explicit GitHub |
Storage
Sources are stored globally at ~/.local/share/opensrc/ (XDG compliant):
~/.local/share/opensrc/
├── sources.json # Index of fetched sources
├── packages/ # npm/pypi/crates packages
│ └── zod/
│ ├── src/
│ ├── package.json
│ └── ...
└── repos/ # GitHub repos
└── github.com/
└── vercel/
└── ai/Override with $OPENSRC_DIR or $XDG_DATA_HOME.
How It Works
Agent calls
executetool with JS code:async () => opensrc.fetch("zod")Code runs in sandboxed
vmcontext with injectedopensrcAPIServer fetches package via opensrc (handles registry lookup, git clone)
Only the result returns to agent context
┌─────────────────────────────────────────────────────────────┐
│ Agent Context │
├─────────────────────────────────────────────────────────────┤
│ Tool call: execute({ code: "async () => opensrc.fetch..." })│
│ ↓ │
│ Result: { success: true, source: { name: "zod", ... } } │
└─────────────────────────────────────────────────────────────┘
↕
┌─────────────────────────────────────────────────────────────┐
│ opensrc-mcp Server │
├─────────────────────────────────────────────────────────────┤
│ Sandbox executes code with injected opensrc API │
│ Full source tree stays here, never sent to agent │
└─────────────────────────────────────────────────────────────┘License
MIT
Available Tools
1 toolexecuteB
Query and mutate fetched source code. Data stays server-side.
Types:
interface Source { type: "npm" | "pypi" | "crates" | "repo"; name: string; version?: string; ref?: string; path: string; fetchedAt: string; repository: string; }
interface FileEntry { path: string; size: number; isDirectory: boolean; }
interface TreeNode { name: string; type: "file" | "dir"; children?: TreeNode[]; }
interface GrepResult { source: string; file: string; line: number; content: string; }
interface AstGrepMatch { file: string; line: number; column: number; text: string; metavars: Record<string, string>; // captured $VAR values }
interface ParsedSpec { type: "npm" | "pypi" | "crates" | "repo"; name: string; version?: string; ref?: string; repoUrl?: string; }
interface FetchedSource { source: Source; alreadyExists: boolean; }
interface RemoveResult { success: boolean; removed: string[]; }
declare const sources: Source[]; declare const cwd: string;
declare const opensrc: { // Read operations list(): Source[]; has(name: string, version?: string): boolean; get(name: string): Source | undefined; files(sourceName: string, glob?: string): Promise<FileEntry[]>; tree(sourceName: string, options?: { depth?: number }): Promise; grep(pattern: string, options?: { sources?: string[]; include?: string; maxResults?: number; }): Promise<GrepResult[]>; astGrep(sourceName: string, pattern: string, options?: { glob?: string; lang?: string | string[]; limit?: number; }): Promise<AstGrepMatch[]>; read(sourceName: string, filePath: string): Promise; readMany(sourceName: string, paths: string[]): Promise<Record<string, string>>; resolve(spec: string): Promise;
// Mutation operations fetch(specs: string | string[], options?: { modify?: boolean; }): Promise<FetchedSource[]>; remove(names: string[]): Promise; clean(options?: { packages?: boolean; repos?: boolean; npm?: boolean; pypi?: boolean; crates?: boolean; }): Promise; };
Fetch spec formats (input to opensrc.fetch):
zod -> npm package (latest or lockfile version)
zod@3.22.0 -> npm specific version
pypi:requests -> Python/PyPI package
crates:serde -> Rust/crates.io package
vercel/ai -> GitHub repo (default branch)
vercel/ai@v3.0.0 -> GitHub repo at tag/branch/commit
Source names (returned in FetchedSource.source.name, used for read/grep):
npm packages: "zod", "drizzle-orm", "@tanstack/react-query"
pypi packages: "requests", "numpy"
crates: "serde", "tokio"
GitHub repos: "github.com/vercel/ai", "github.com/anthropics/sdk"
IMPORTANT: After fetching, always use source.name for subsequent API calls.
Examples:
// List all fetched sources async () => { return opensrc.list().map(s => ({ name: s.name, type: s.type, version: s.version || s.ref })); }
// Fetch and explore structure with tree() async () => { const [{ source }] = await opensrc.fetch("zod"); return await opensrc.tree(source.name, { depth: 2 }); }
// Fetch a GitHub repo and read key files async () => { const [{ source }] = await opensrc.fetch("vercel/ai"); const files = await opensrc.readMany(source.name, [ "package.json", "README.md", "src/index.ts" ]); return { sourceName: source.name, files: Object.keys(files) }; }
// readMany with globs async () => { return await opensrc.readMany("zod", ["packages/*/package.json"]); }
// Fetch multiple packages async () => { const results = await opensrc.fetch(["zod", "drizzle-orm", "hono"]); return results.map(r => r.source.name); }
// Text search with grep async () => { const results = await opensrc.grep("export function parse", { sources: ["zod"], include: "*.ts" }); if (matches.length === 0) return "No matches"; const { source, file, line } = matches[0]; const content = await opensrc.read(source, file); return content.split("\n").slice(line - 1, line + 29).join("\n"); }
// Search across all sources
async () => {
const results = await opensrc.grep("throw new Error", { include: "*.ts", maxResults: 20 });
return results.map(r => ${r.source}:${r.file}:${r.line});
}
// AST search with astGrep (use $VAR for single node, $$$VAR for multiple) // Patterns: "function $NAME($$$)" | "const $X = $Y" | "useState($INIT)" | "$OBJ.$METHOD($$$)" async () => { const matches = await opensrc.astGrep("zod", "function $NAME($$$ARGS)", { glob: "**/*.ts", limit: 10 }); return matches.map(m => ({ file: m.file, name: m.metavars.NAME, line: m.line })); }
// Find entry points async () => { const files = await opensrc.files("github.com/vercel/ai", "**/{index,main}.{ts,js}"); if (files.length > 0) return await opensrc.read("github.com/vercel/ai", files[0].path); return "No entry point found"; }
// Batch read with error handling async () => { const files = await opensrc.readMany("zod", ["src/index.ts", "src/types.ts", "nonexistent.ts"]); // Failed reads have "[Error: ...]" as value return Object.keys(files).filter(p => !files[p].startsWith("[Error:")); }
// Remove sources async () => { return await opensrc.remove(["zod", "github.com/vercel/ai"]); }
| Name | Required | Description | Default |
|---|---|---|---|
| code | Yes | JavaScript async arrow function to execute |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description mentions that data stays server-side, which is a key behavioral trait. It also indicates the tool supports both query and mutation operations. However, without annotations, it lacks details on side effects, error handling, or resource limits. The extensive description of the opensrc API indirectly clarifies behavior but is not focused on the tool itself.
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 excessively long, containing type definitions, a full API declare block, and many examples. While the first two sentences are front-loaded and clear, the rest is verbose and repetitive. Many details could be moved to reference documentation, making the tool description hard to parse quickly.
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 description is comprehensive about the environment (opensrc API) but lacks explicit information about the tool's return value, error handling, or execution context. Given the complexity of the runtime, the description covers the code execution environment well, but not the tool's own behavior completely. The output schema is absent, so some completeness is lost.
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 input schema has 100% coverage with a description for the only parameter ('code' as JavaScript async arrow function). The description adds value by providing extensive examples of valid code snippets, but it does not explain parameter semantics beyond what the schema already states. The baseline of 3 is appropriate since schema coverage is complete.
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 that the tool queries and mutates fetched source code and that data stays server-side. This provides a clear verb+resource description, distinguishing the tool from hypothetical others that might expose data. However, the purpose could be slightly more specific about executing user-provided JavaScript code.
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 does not explicitly state when to use this tool versus alternatives, but since there are no siblings, this is less critical. It provides examples of common use cases like fetching and exploring code, which imply usage. However, there is no guidance on when not to use it (e.g., for non-code tasks).
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. Dates show when Glama detected each change.
1 tool update
v0.3.0- First observed
execute
TDQS
There is only one tool named 'execute', so disambiguation is not applicable. However, the tool description indicates it handles both querying and mutating source code, which could be seen as combining multiple distinct operations into a single tool, potentially causing confusion about its scope.
With only one tool, naming consistency is trivially perfect. The tool name 'execute' follows a clear verb pattern, and there are no other tools to cause inconsistency.
The server has only one tool, which is too few for its apparent purpose of managing and analyzing source code across multiple ecosystems (npm, pypi, crates, repos). The tool 'execute' bundles many operations (list, fetch, read, grep, etc.), making the surface overly simplistic for the domain's complexity.
The tool surface is severely incomplete. While the underlying API (opensrc) provides comprehensive operations (e.g., list, fetch, read, grep, astGrep, remove), the MCP server exposes only a single 'execute' tool, forcing all functionality through one interface. This creates significant gaps in discoverability and usability, as agents cannot directly access specific operations like fetching or searching without interpreting the tool's description and examples.
Maintenance
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
Search GitHub, npm, PyPI, StackOverflow, ArXiv from one MCP — built for coding agents.
An MCP server that gives your AI access to the source code and docs of all public github repos
Capability registry for the agentic economy. Semantic search over verified MCP server listings.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceMCP server that gives AI agents deep code understanding across multiple git repositories, combining git lifecycle management, Zoekt-based trigram code search, and cross-repo dependency analysis.MIT
- AlicenseNot gradedqualityBmaintenanceAgent-safe code retrieval MCP server that indexes repositories and provides semantic search, file navigation, call graph analysis, and bounded file reading tools for coding agents.3,448,4193AGPL 3.0
- AlicenseNot gradedqualityBmaintenanceA local MCP server that indexes TypeScript/JavaScript projects and returns budget-aware, dependency-optimized context packs for AI coding assistants.1MIT
- AlicenseNot gradedqualityCmaintenanceA local MCP server that parses codebases into semantic chunks, indexes them in SQLite with vector embeddings, and exposes MCP tools for LLM agents to query.MIT
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/dmmulroy/opensrc-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server