legis:toc
Retrieve a compact table of contents for German laws to navigate large legal documents efficiently. Specify jurisdiction and law identifier to get section numbers and headings.
Instructions
Get table of contents for a law — compact list of section numbers and headings. Much lighter than legis:get for navigating large laws. BUND: id is just the law abbreviation (e.g., "bgb", "stgb"). Länder: id from legis:search results.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | Law identifier. BUND: law abbreviation (e.g., "bgb"). Länder: ID from legis:search. | |
| state | Yes | Jurisdiction (e.g., "BUND", "BW", "NW") | |
| from | No | Start at section (e.g., "§ 823", "Art 1"). Inclusive. | |
| to | No | End at section (e.g., "§ 853"). Inclusive. | |
| depth | No | Max depth level (0=top structure only, 1=sections, 2=subsections, 3=norms) |
Implementation Reference
- src/providers/legis/index.ts:90-137 (handler)The `handleToc` method in `LegisProvider` implements the logic for `legis:toc`, including calling the adapter's TOC function (or falling back to parsing the document) and applying optional depth and range filters.
private async handleToc(args: Record<string, unknown>): Promise<ToolResult> { const { id, state, from, to, depth } = args as { id: string; state: string; from?: string; to?: string; depth?: number; }; const adapter = this.getAdapter(state); let entries: TocEntry[]; if (adapter.toc) { entries = await adapter.toc(state, id); } else { // Default: extract headings from full document markdown const entry = await adapter.get(state, id); entries = []; for (const line of entry.content.split('\n')) { const m = line.match(/^(#{1,6})\s+(.+)/); if (!m) continue; const d = m[1].length - 1; // h1→0, h2→1, etc. const nm = m[2].match(/^(§§?\s*\S+|Art\.?\s*\S+)\s*(.*)/); entries.push({ depth: d, num: nm?.[1] || '', title: nm?.[2] || m[2] }); } } // Apply depth filter if (depth !== undefined) entries = entries.filter((e) => e.depth <= depth); // Apply range filter if (from || to) { const norm = (s: string) => s.replace(/\s+/g, '').toLowerCase(); const fromN = from ? norm(from) : null; const toN = to ? norm(to) : null; let inRange = !fromN; entries = entries.filter((e) => { const n = norm(e.num); if (fromN && n === fromN) inRange = true; if (!inRange) return false; if (toN && n === toN) { inRange = false; return true; } return true; }); } const lines = entries.map((e) => { const indent = ' '.repeat(e.depth); if (!e.num) return `${indent}**${e.title}**`; return e.title ? `${indent}${e.num} ${e.title}` : `${indent}${e.num}`; }); return { content: [{ type: 'text', text: `${entries.length} entries:\n\n${lines.join('\n')}` }] }; } - src/providers/legis/tools/index.ts:33-46 (registration)The `legis:toc` tool definition, including its input schema and description, is defined in `legisTools` array.
name: 'legis:toc', description: 'Get table of contents for a law — compact list of section numbers and headings. ' + 'Much lighter than legis:get for navigating large laws. ' + 'BUND: id is just the law abbreviation (e.g., "bgb", "stgb"). ' + 'Länder: id from legis:search results.', inputSchema: z.object({ id: z.string().describe('Law identifier. BUND: law abbreviation (e.g., "bgb"). Länder: ID from legis:search.'), state: stateEnum.describe('Jurisdiction (e.g., "BUND", "BW", "NW")'), from: z.string().optional().describe('Start at section (e.g., "§ 823", "Art 1"). Inclusive.'), to: z.string().optional().describe('End at section (e.g., "§ 853"). Inclusive.'), depth: z.number().optional().describe('Max depth level (0=top structure only, 1=sections, 2=subsections, 3=norms)'), }), },