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 "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., "@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.
1 tool update
v0.3.0- First observed
execute
TDQS
Scored across 1 tool
With only one tool, there is no possibility of confusion between tools. The single tool encompasses a well-defined API, and its purpose is clearly described in the description.
The server has a single tool named 'execute', which is consistent in itself. While the name is generic, there are no other tools to compare against, so no naming inconsistencies exist.
The domain covers fetching, searching, reading, and managing source code from multiple ecosystems, which is a broad scope. Exposing all of this through a single monolithic tool is overly condensed; separate tools for distinct operations (e.g., fetch, read, grep) would be more appropriate for agent discoverability.
The tool covers listing, fetching, reading, searching (grep and astGrep), and removal of sources, which is comprehensive for exploration. However, it lacks explicit update/edit capabilities for source files and no direct way to modify code, leaving a minor gap in mutation workflows.
Maintenance
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.2,693,148 npm3AGPL 3.0
- AlicenseNot gradedqualityCmaintenanceA 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