Skip to main content
Glama
josemvelez78

mcp-europe-business

validate_siret

Read-onlyIdempotent

Validates French SIRET numbers using the Luhn algorithm, extracting SIREN and establishment identifiers, and handling the La Poste special case automatically.

Instructions

Validates a French SIRET (14-digit company establishment number) using the official Luhn algorithm. The first 9 digits are the SIREN (company identifier) and the last 5 identify the specific establishment. Returns { valid: boolean, siren: string, establishment: string, siret: string }. Handles the La Poste special case automatically.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
siretYes14-digit French SIRET, with or without spaces/dashes. Example: '732 829 320 00074'

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
validYes
sirenNo
establishmentNo
siretNo
reasonNo

Implementation Reference

  • The validate_siret tool handler function that validates a French SIRET (14-digit company establishment number) using the Luhn algorithm. It strips spaces/dashes, checks for exactly 14 digits, handles the La Poste special case (starts with 356000000), applies the Luhn algorithm with alternating doubling, and returns {valid, siren, establishment, siret}.
    // ── 8. Validate French SIRET ──
    server.registerTool("validate_siret", {
      description: "Validates a French SIRET (14-digit company establishment number) using the official Luhn algorithm. The first 9 digits are the SIREN (company identifier) and the last 5 identify the specific establishment. Returns { valid: boolean, siren: string, establishment: string, siret: string }. Handles the La Poste special case automatically.",
      inputSchema: { siret: z.string().describe("14-digit French SIRET, with or without spaces/dashes. Example: '732 829 320 00074'") },
      outputSchema: { valid: z.boolean(), siren: z.string().optional(), establishment: z.string().optional(), siret: z.string().optional(), reason: z.string().optional() },
          annotations: { title: "Validate French SIRET", readOnlyHint: true, idempotentHint: true, openWorldHint: false }
    }, async ({ siret }) => {
      const clean = siret.replace(/[\s\-]/g, "");
      if (!/^\d{14}$/.test(clean)) return { content: [{ type: "text", text: JSON.stringify({ valid: false, reason: "SIRET must have exactly 14 digits" }) }] };
      if (clean.startsWith("356000000")) {
        const valid = clean.split("").reduce((acc, d) => acc + parseInt(d), 0) % 5 === 0;
        return { content: [{ type: "text", text: JSON.stringify({ valid, siren: clean.substring(0, 9), establishment: clean.substring(9), siret: clean }) }] };
      }
      let sum = 0;
      for (let i = 0; i < 14; i++) {
        let digit = parseInt(clean[i]);
        if (i % 2 === 0) { digit *= 2; if (digit > 9) digit -= 9; }
        sum += digit;
      }
      return { content: [{ type: "text", text: JSON.stringify({ valid: sum % 10 === 0, siren: clean.substring(0, 9), establishment: clean.substring(9), siret: clean }) }] };
    });
  • index.js:199-203 (registration)
    Registration of the validate_siret tool via server.registerTool(), including its description, inputSchema, outputSchema, and annotations (title: 'Validate French SIRET', readOnlyHint, idempotentHint).
    server.registerTool("validate_siret", {
      description: "Validates a French SIRET (14-digit company establishment number) using the official Luhn algorithm. The first 9 digits are the SIREN (company identifier) and the last 5 identify the specific establishment. Returns { valid: boolean, siren: string, establishment: string, siret: string }. Handles the La Poste special case automatically.",
      inputSchema: { siret: z.string().describe("14-digit French SIRET, with or without spaces/dashes. Example: '732 829 320 00074'") },
      outputSchema: { valid: z.boolean(), siren: z.string().optional(), establishment: z.string().optional(), siret: z.string().optional(), reason: z.string().optional() },
          annotations: { title: "Validate French SIRET", readOnlyHint: true, idempotentHint: true, openWorldHint: false }
  • Input schema (z.string() for 'siret') and output schema (valid boolean, siren string optional, establishment string optional, siret string optional, reason string optional) for the validate_siret tool.
    description: "Validates a French SIRET (14-digit company establishment number) using the official Luhn algorithm. The first 9 digits are the SIREN (company identifier) and the last 5 identify the specific establishment. Returns { valid: boolean, siren: string, establishment: string, siret: string }. Handles the La Poste special case automatically.",
    inputSchema: { siret: z.string().describe("14-digit French SIRET, with or without spaces/dashes. Example: '732 829 320 00074'") },
    outputSchema: { valid: z.boolean(), siren: z.string().optional(), establishment: z.string().optional(), siret: z.string().optional(), reason: z.string().optional() },
Behavior4/5

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

Annotations already indicate readOnly and idempotent. The description adds behavioral context beyond annotations: mentions the Luhn algorithm, return fields, and automatic handling of the La Poste special case. No contradictions.

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?

Three focused sentences with no fluff. Front-loaded with the main purpose, then details on structure, return, and special case handling. Every sentence adds value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's simplicity (single parameter) and the presence of an output schema, the description covers all necessary information: purpose, input format, output fields, and a special case. No gaps.

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?

The single parameter 'siret' has 100% schema coverage, but the description adds meaning beyond the schema by explaining the SIRET structure (SIREN + establishment) and providing an example with spaces/dashes.

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?

The description clearly states the tool validates a French SIRET using the Luhn algorithm, explains its structure (SIREN + establishment), and lists the return fields. It is specific and distinct from sibling validation tools for other identifiers.

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?

The description implicitly indicates when to use this tool (when a SIRET number needs validation), but does not explicitly compare to alternatives or provide when-not usage. The sibling tools are for different identifier types, so the context is clear.

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/josemvelez78/mcp-europe-business'

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