Skip to main content
Glama
metaneutrons

German Legal MCP Server

by metaneutrons

icu:get_document

Retrieve full-text CJEU decisions or opinions from InfoCuria by case or CELEX number. Extract specific sections like paragraph ranges or headings, or save documents to files for legal research.

Instructions

Retrieve a CJEU decision or opinion from InfoCuria by case number or CELEX number. Returns full text in Markdown with Randnummern as [Rn. 5]{.rn}. Use section for partial content: "Rn 5-12", heading text, or "lines:100-200". Use save_path to save to file instead of returning content.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
case_idYesPublished case ID (e.g., "C-476/17") or CELEX number (e.g., "62017CJ0476")
languageYesLanguage code (default: DE)DE
sectionNoExtract section: "Rn 5-12", heading text, or "lines:100-200"
save_pathNoSave full document to this file path instead of returning content

Implementation Reference

  • The `handleGetDocument` method implements the logic for fetching, converting, and (optionally) saving a document from InfoCuria.
    private async handleGetDocument(args: Record<string, unknown>): Promise<ToolResult> {
      const { case_id, language = 'DE', section, save_path } = args as {
        case_id: string; language?: string; section?: string; save_path?: string;
      };
    
      // Resolve case_id to logicDocId via search
      const logicDocId = await this.resolveLogicDocId(case_id, language as string);
      if (!logicDocId) {
        return { content: [{ type: 'text', text: `No document found for "${case_id}" in ${language}` }], isError: true };
      }
    
      const numericId = logicDocId.replace('id_', '');
      logger.info('Fetching document', { case_id, numericId, language });
    
      const response = await axios.get(`${BLOB_URL}/${numericId}/${language.toUpperCase()}/html`, {
        headers: { 'Origin': 'https://infocuria.curia.europa.eu' },
        responseType: 'text',
      });
    
      const markdown = this.converter.convert(response.data);
      validateConversion(markdown, 'InfoCuria');
    
      // Section extraction
      if (section) {
        const extracted = this.extractSection(markdown, section);
        if (!extracted) {
          return { content: [{ type: 'text', text: `Section "${section}" not found.` }], isError: true };
        }
        return { content: [{ type: 'text', text: extracted }] };
      }
    
      const fullDoc = `# ${case_id}\n\n---\n\n${markdown}`;
    
      if (save_path) {
        const { writeFile } = await import('fs/promises');
        await writeFile(save_path, fullDoc, 'utf-8');
        return { content: [{ type: 'text', text: `Saved to ${save_path}\n\nCase: ${case_id}\nLanguage: ${language}` }] };
      }
    
      return { content: [{ type: 'text', text: fullDoc }] };
    }
  • The input schema and tool description for `icu:get_document`.
    {
      name: 'icu:get_document',
      description:
        'Retrieve a CJEU decision or opinion from InfoCuria by case number or CELEX number. ' +
        'Returns full text in Markdown with Randnummern as [Rn. 5]{.rn}. ' +
        'Use `section` for partial content: "Rn 5-12", heading text, or "lines:100-200". ' +
        'Use `save_path` to save to file instead of returning content.',
      inputSchema: z.object({
        case_id: z.string().describe('Published case ID (e.g., "C-476/17") or CELEX number (e.g., "62017CJ0476")'),
        language: z.string().optional().default('DE').describe('Language code (default: DE)'),
        section: z.string().optional().describe('Extract section: "Rn 5-12", heading text, or "lines:100-200"'),
        save_path: z.string().optional().describe('Save full document to this file path instead of returning content'),
      }),
    },
  • The `handleToolCall` method routes the `icu:get_document` call to its handler.
    if (toolName === 'icu:get_document') return this.handleGetDocument(args);
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, description carries full burden and succeeds well: discloses Markdown output format, specific Randnummern syntax ([Rn. 5]{.rn}), and the dual-mode behavior (return content vs. file save via save_path). Minor gap: no mention of error behavior when case_id not found.

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?

Four sentences, zero waste. Front-loaded with core purpose, followed by output format specifics, then parameter usage guidance. Every sentence delivers unique information not redundant with schema or title.

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 legal document retrieval tool with 4 parameters and no output schema, description adequately compensates by explaining return format and content structure. Absence of error handling documentation prevents a 5, but coverage is sufficient for correct invocation.

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?

Though schema coverage is 100% (baseline 3), description adds crucial usage examples for section ('Rn 5-12', heading text, 'lines:100-200') and clarifies save_path's side effect ('instead of returning content'). These behavioral details exceed raw schema definitions.

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?

Excellent specificity: 'Retrieve a CJEU decision or opinion from InfoCuria' provides exact verb, resource type, and source system. Distinguishes clearly from siblings like eul:get_document (EU legislation) and arxiv:get (academic papers) by specifying CJEU legal documents.

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?

Clear input requirements (case number or CELEX number) implicitly signal this is for known documents versus searching. However, it doesn't explicitly reference sibling icu:search for discovery workflows or state prerequisites like 'use search first if case_id unknown'.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

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/metaneutrons/german-legal-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server