Files
2026-01-23 21:45:57 +00:00

236 lines
5.2 KiB
Markdown

# opensrc API Reference
## Tool
Use the **opensrc MCP server** via single tool:
| Tool | Purpose |
|------|---------|
| `opensrc_execute` | All operations (fetch, read, grep, files, remove, etc.) |
Takes a `code` parameter: JavaScript async arrow function executed server-side. Source trees stay on server, only results return.
## API Surface
### Read Operations
```typescript
// List all fetched sources
opensrc.list(): Source[]
// Check if source exists
opensrc.has(name: string, version?: string): boolean
// Get source metadata
opensrc.get(name: string): Source | undefined
// List files with optional glob
opensrc.files(sourceName: string, glob?: string): Promise<FileEntry[]>
// Get directory tree structure (default depth: 3)
opensrc.tree(sourceName: string, options?: { depth?: number }): Promise<TreeNode>
// Regex search file contents
opensrc.grep(pattern: string, options?: GrepOptions): Promise<GrepResult[]>
// AST-based semantic code search
opensrc.astGrep(sourceName: string, pattern: string, options?: AstGrepOptions): Promise<AstGrepMatch[]>
// Read single file
opensrc.read(sourceName: string, filePath: string): Promise<string>
// Batch read multiple files (supports globs!)
opensrc.readMany(sourceName: string, paths: string[]): Promise<Record<string, string>>
// Parse fetch spec
opensrc.resolve(spec: string): Promise<ParsedSpec>
```
### Mutation Operations
```typescript
// Fetch packages/repos
opensrc.fetch(specs: string | string[], options?: { modify?: boolean }): Promise<FetchedSource[]>
// Remove sources
opensrc.remove(names: string[]): Promise<RemoveResult>
// Clean by type
opensrc.clean(options?: CleanOptions): Promise<RemoveResult>
```
## Types
### Source
```typescript
interface Source {
type: "npm" | "pypi" | "crates" | "repo";
name: string; // Use this for all subsequent calls
version?: string;
ref?: string;
path: string;
fetchedAt: string;
repository: string;
}
```
### FetchedSource
```typescript
interface FetchedSource {
source: Source; // IMPORTANT: use source.name for subsequent calls
alreadyExists: boolean;
}
```
### GrepOptions
```typescript
interface GrepOptions {
sources?: string[]; // Filter to specific sources
include?: string; // File glob pattern (e.g., "*.ts")
maxResults?: number; // Limit results (default: 100)
}
```
### GrepResult
```typescript
interface GrepResult {
source: string;
file: string;
line: number;
content: string;
}
```
### AstGrepOptions
```typescript
interface AstGrepOptions {
glob?: string; // File glob pattern (e.g., "**/*.ts")
lang?: string | string[]; // Language(s): "js", "ts", "tsx", "html", "css"
limit?: number; // Max results (default: 1000)
}
```
### AstGrepMatch
```typescript
interface AstGrepMatch {
file: string;
line: number;
column: number;
endLine: number;
endColumn: number;
text: string; // Matched code text
metavars: Record<string, string>; // Captured $VAR → text
}
```
#### AST Pattern Syntax
| Pattern | Matches |
|---------|---------|
| `$NAME` | Single node, captures to metavars |
| `$$$ARGS` | Zero or more nodes (variadic), captures |
| `$_` | Single node, no capture |
| `$$$` | Zero or more nodes, no capture |
### FileEntry
```typescript
interface FileEntry {
path: string;
size: number;
isDirectory: boolean;
}
```
### TreeNode
```typescript
interface TreeNode {
name: string;
type: "file" | "dir";
children?: TreeNode[]; // only for dirs
}
```
### CleanOptions
```typescript
interface CleanOptions {
packages?: boolean;
repos?: boolean;
npm?: boolean;
pypi?: boolean;
crates?: boolean;
}
```
### RemoveResult
```typescript
interface RemoveResult {
success: boolean;
removed: string[];
}
```
## Error Handling
Operations throw on errors. Wrap in try/catch if needed:
```javascript
async () => {
try {
const content = await opensrc.read("zod", "missing.ts");
return content;
} catch (e) {
return { error: e.message };
}
}
```
`readMany` returns errors as string values prefixed with `[Error:`:
```javascript
const files = await opensrc.readMany("zod", ["exists.ts", "missing.ts"]);
// { "exists.ts": "content...", "missing.ts": "[Error: ENOENT...]" }
// Filter successful reads
const successful = Object.entries(files)
.filter(([_, content]) => !content.startsWith("[Error:"));
```
## Package Spec Formats
| Format | Example | Source Name After Fetch |
|--------|---------|------------------------|
| `<name>` | `"zod"` | `"zod"` |
| `<name>@<version>` | `"zod@3.22.0"` | `"zod"` |
| `pypi:<name>` | `"pypi:requests"` | `"requests"` |
| `crates:<name>` | `"crates:serde"` | `"serde"` |
| `owner/repo` | `"vercel/ai"` | `"github.com/vercel/ai"` |
| `owner/repo@ref` | `"vercel/ai@v1.0.0"` | `"github.com/vercel/ai"` |
| `gitlab:owner/repo` | `"gitlab:org/repo"` | `"gitlab.com/org/repo"` |
## Critical Pattern
**Always capture `source.name` from fetch results:**
```javascript
async () => {
const [{ source }] = await opensrc.fetch("vercel/ai");
// GitHub repos: "vercel/ai" → "github.com/vercel/ai"
const sourceName = source.name;
// Use sourceName for ALL subsequent calls
const files = await opensrc.files(sourceName, "src/**/*.ts");
return files;
}
```