dacli - API Specification

1. Overview

This specification defines the MCP tools provided by dacli. The tools are available via two interfaces:

  • MCP Server (dacli-mcp): For LLM integration via MCP protocol over stdio

  • CLI (dacli): For direct command-line usage (see 06_cli_specification.adoc)

1.1. MCP Communication

Transport: stdio (standard input/output)
Protocol: MCP (Model Context Protocol)

The MCP server is spawned as a subprocess by an MCP client (e.g., Claude Desktop) and communicates via JSON-RPC over stdio.

1.2. Authentication

The current version does not require authentication (single-tenant, local access only).

2. Data Models

2.1. SectionLocation

Describes the position of a section in a source file.

{
  "file": "string",        // Relative path to file
  "start_line": "integer", // 1-based start line
  "end_line": "integer"    // 1-based end line (inclusive)
}

2.2. Section

Represents a section in the document.

{
  "path": "string",           // Hierarchical path (e.g., "chapter-1.section-2")
  "title": "string",          // Section title
  "level": "integer",         // Nesting depth (1 = chapter)
  "location": "SectionLocation",
  "children": ["Section"]     // Subsections (optional)
}

2.3. Element

Represents a special element (table, code, diagram).

{
  "type": "string",           // "admonition" | "code" | "image" | "list" | "plantuml" | "table"
  "path": "string",           // Path to containing section
  "index": "integer",         // Index within section
  "location": "SectionLocation"
}

2.4. SearchResult

Search result with context.

{
  "path": "string",           // Path to match location
  "line": "integer",          // Line number
  "context": "string",        // Surrounding text
  "score": "number"           // Relevance score (0-1)
}

2.5. Metadata

Metadata of a document or section.

{
  "path": "string",           // Path (or null for project)
  "file": "string",           // Source file
  "word_count": "integer",    // Word count
  "last_modified": "datetime",// Last modified (ISO 8601)
  "subsection_count": "integer",
  "includes": ["string"]      // List of include paths
}

2.6. ValidationResult

Result of structure validation.

{
  "valid": "boolean",
  "errors": [{
    "type": "string",         // "unresolved_include" | "circular_include" | ...
    "path": "string",
    "message": "string"
  }],
  "warnings": [{
    "type": "string",
    "path": "string",
    "message": "string"
  }]
}

2.7. ErrorResponse

Standardized error response.

{
  "error": {
    "code": "string",         // Error code (e.g., "PATH_NOT_FOUND")
    "message": "string",      // Human-readable error message
    "details": "object"       // Additional details (optional)
  }
}

3. Path Format Convention

Section paths use hybrid notation combining colons and dots:

  • Colon (:) - Separates document slug from first-level section

  • Dot (.) - Separates nested sections within the same document

3.1. Format Rules

Level Format Example

0 (Document root)

document-slug

"my-doc"

1 (First-level section)

document:section

"my-doc:introduction"

2 (Subsection)

document:section.subsection

"my-doc:introduction.goals"

3+ (Deeper nesting)

document:section.sub.subsub

"my-doc:intro.goals.technical"

3.2. Important Notes

  • Use colon only once to separate document from section

  • Use dots for all nested levels (Level 2+)

  • Paths are case-insensitive and slugified (lowercase, hyphens)

3.3. Common Mistakes

❌ Incorrect ✅ Correct

doc:section:subsection

doc:section.subsection

doc.section.subsection

doc:section.subsection

doc/section/subsection

doc:section.subsection

3.4. Error Handling for Invalid Paths

When a path with multiple colons is provided (e.g., doc:a:b), the system:

  1. Normalizes the path by converting extra colons to dots (doc:a.b)

  2. Returns PATH_NOT_FOUND error with:

    • requested_path: The original malformed path

    • corrected_path: The normalized path

    • hint: Explanation of correct format

    • suggestions: Similar valid paths

Example error response:

{
  "error": {
    "code": "PATH_NOT_FOUND",
    "message": "Section 'doc:intro:goals' not found",
    "details": {
      "requested_path": "doc:intro:goals",
      "corrected_path": "doc:intro.goals",
      "hint": "Use colon (:) only once to separate document from section. Use dots (.) for nested sections. Example: doc:intro.goals",
      "suggestions": ["doc:introduction", "doc:introduction.goals"]
    }
  }
}

4. MCP Tools

4.1. Navigation Tools

4.1.1. get_structure

Retrieves the hierarchical document structure.

Use Case: UC-01

Parameter Description

max_depth (int >= 0, optional)

Maximum depth of returned structure. Default: unlimited. Must be non-negative.

Response 200:

{
  "root": {
    "path": "",
    "title": "MCP Documentation Server",
    "level": 0,
    "children": [
      {
        "path": "introduction",
        "title": "1. Introduction",
        "level": 1,
        "children": [
          {
            "path": "introduction.goals",
            "title": "1.1 Goals",
            "level": 2,
            "children": []
          }
        ]
      }
    ]
  },
  "total_sections": 42
}

4.1.2. get_section

Reads the content of a specific section.

Use Case: UC-02

Parameter Description

path (string, required)

Hierarchical path to section (e.g., "introduction.goals")

Response 200:

{
  "path": "introduction.goals",
  "title": "1.1 Goals",
  "content": "= Goals\n\nThe main goals of this project are...",
  "location": {
    "file": "chapters/01_introduction.adoc",
    "start_line": 15,
    "end_line": 42
  },
  "format": "asciidoc"
}

Response 404:

{
  "error": {
    "code": "PATH_NOT_FOUND",
    "message": "Section 'introduction.goals' not found",
    "details": {
      "requested_path": "introduction.goals",
      "suggestions": ["introduction.quality-goals", "introduction.stakeholders"]
    }
  }
}

4.1.3. get_sections_at_level

Retrieves all sections at a specific level.

Use Case: UC-01 (Extension)

Parameter Description

level (int >= 1, required)

Desired nesting depth. Must be positive (1 = chapter, 2 = section, etc.)

Response 200:

{
  "level": 1,
  "sections": [
    {
      "path": "introduction",
      "title": "1. Introduction"
    },
    {
      "path": "constraints",
      "title": "2. Constraints"
    }
  ],
  "count": 12
}

4.2. Content Access Tools

4.2.1. get_elements

Retrieves elements of a specific type.

Use Case: UC-05

Parameter Description

element_type (string, optional)

Element type: code, table, image, plantuml, list, admonition. None returns all elements. Invalid types return a warning (CLI) or error (MCP).

section_path (string, optional)

Restriction to specific section

Response 200:

{
  "type": "code",
  "elements": [
    {
      "type": "code",
      "path": "architecture.decisions",
      "index": 0,
      "location": {
        "file": "chapters/09_decisions.adoc",
        "start_line": 25,
        "end_line": 35
      },
      "attributes": {
        "language": "python",
        "content": "def example():\n    return 'hello world'"
      }
    }
  ],
  "count": 1
}
The attributes field contains element-specific data including content (Issue #159). For code elements, it includes language and content fields. For table elements, it includes columns, rows, and content (raw table text). For list elements, it includes list_type and content (all list items). For image elements, it includes alt, src/target, and optionally title. For plantuml/diagram elements, it includes format, optionally name, and content (diagram source). For admonition elements, it includes admonition_type and content.
**Response 400:**
[source,json]

{ "error": { "code": "INVALID_TYPE", "message": "Unknown element type 'charts'", "details": { "valid_types": ["admonition", "code", "image", "list", "plantuml", "table"] } } }

'''

==== search

Searches documentation content.

**Use Case:** UC-04

[cols="1,3"]
|===
| Parameter | Description

| `query` (string, required)
| Search term (case-insensitive)

| `scope` (string, optional)
| Restriction to path prefix (e.g., "/architecture")

| `max_results` (int >= 0, optional)
| Maximum results to return (default: 20). Must be non-negative.
|===

**Response 200:**
[source,json]

{ "query": "atomic write", "results": [ { "path": "decisions.adr-004", "line": 12, "context": "…​implements atomic writes using a backup-and-replace strategy…​", "score": 0.95 }, { "path": "runtime.update-scenario", "line": 5, "context": "…​The process must be atomic to ensure data integrity…​", "score": 0.78 } ], "total_results": 2, "search_time_ms": 45 }

=== Content Manipulation Tools

==== update_section

Updates the content of a section.

**Use Case:** UC-03

[cols="1,3"]
|===
| Parameter | Description

| `path` (string, required)
| Hierarchical path to section (e.g., "introduction.goals")

| `content` (string, required)
| New section content

| `preserve_title` (bool, optional)
| Whether to preserve the original section title (default: true). When true, the original title is kept regardless of content. When false, the title from the provided content is used (content must include a section title starting with `=` or `#`, otherwise the update fails with error).

| `expected_hash` (string, optional)
| Hash for optimistic locking - update fails if current content hash doesn't match
|===

**Response 200:**
[source,json]

{ "success": true, "path": "introduction.goals", "location": { "file": "chapters/01_introduction.adoc", "start_line": 15, "end_line": 38 }, "previous_hash": "a1b2c3d4", "new_hash": "e5f6g7h8" }

**Response 404:**
[source,json]

{ "error": { "code": "PATH_NOT_FOUND", "message": "Section 'introduction.goals' not found" } }

**Response 500:**
[source,json]

{ "error": { "code": "WRITE_FAILED", "message": "Failed to write changes to file", "details": { "file": "chapters/01_introduction.adoc", "reason": "Permission denied" } } }

'''

==== insert_content

Inserts content relative to a section.

**Use Case:** UC-09

[cols="1,3"]
|===
| Parameter | Description

| `path` (string, required)
| Hierarchical path to reference section

| `position` (string, required)
| Where to insert: "before" (adds blank line after content if next line is heading), "after" (inserts after section end *including all child sections*), or "append" (inserts at end of section's own content, before children)

| `content` (string, required)
| Content to insert
|===

**Response 200:**
[source,json]

{ "success": true, "inserted_at": { "file": "chapters/01_introduction.adoc", "line": 43 } }

'''

==== update_element (planned)

[NOTE]
====
This tool is planned but not yet implemented.
====

Replaces a specific element (code block, table, etc.).

**Use Case:** UC-10

[cols="1,3"]
|===
| Parameter | Description

| `path` (string, required)
| Hierarchical path to section

| `index` (int, required)
| Index of element within section (0-based)

| `content` (string, required)
| New element content
|===

=== Meta-Information Tools

==== get_metadata

Retrieves metadata about the project or a specific section.

**Use Case:** UC-06

[cols="1,3"]
|===
| Parameter | Description

| `path` (string, optional)
| Path to section. If None, returns project-level metadata.
|===

**Response 200 (Project):**
[source,json]

{ "path": null, "project_name": "MCP Documentation Server", "total_files": 15, "total_sections": 87, "total_words": 12450, "last_modified": "2026-01-20T14:30:00Z", "formats": ["asciidoc", "markdown"] }

**Response 200 (Section):**
[source,json]

{ "path": "decisions", "title": "9. Architecture Decisions", "file": "chapters/09_decisions.adoc", "word_count": 2340, "last_modified": "2026-01-19T10:15:00Z", "subsection_count": 5, "includes": [] }

'''

==== get_dependencies

Retrieves include dependencies between documentation files.

**Use Case:** UC-06 (Extension)

**Response 200:**
[source,json]

{ "include_tree": { "arc42.adoc": [ "chapters/01_introduction.adoc", "chapters/02_constraints.adoc" ] }, "cross_references": [] }

NOTE: `cross_references` is reserved for future use and currently returns an empty list.

'''

==== validate_structure

Validates the document structure.

**Use Case:** UC-07

**Response 200:**
[source,json]

{ "valid": true, "errors": [], "warnings": [ { "type": "orphaned_file", "path": "chapters/unused.adoc", "message": "File is not included in any document" } ], "validation_time_ms": 120 }

**Response 200 (with errors):**
[source,json]

{ "valid": false, "errors": [ { "type": "unresolved_include", "path": "chapters/01_introduction.adoc:15", "message": "Cannot resolve include: 'missing.adoc'" }, { "type": "circular_include", "path": "chapters/03_context.adoc", "message": "Circular include detected: context.adoc → technical.adoc → context.adoc" } ], "warnings": [] }

=== System Tools (planned)

[NOTE]
====
The following tools are planned but not yet implemented. The MCP server currently rebuilds the index automatically after write operations.
====

==== get_health (planned)

Returns server health status and index information.

==== reindex (planned)

Triggers manual reindexing of the documentation.

== CLI Interface

NOTE: The CLI specification is in a separate file: `06_cli_specification.adoc`

The CLI interface allows using all MCP tools via the command line,
especially for LLMs without MCP support.

== Error Code Reference

Error responses are returned as dictionaries with an `error` key:

[cols="1,3"]
|===
| Code | Description

| `PATH_NOT_FOUND` | Requested section path does not exist
| `ELEMENT_NOT_FOUND` | Element at specified index does not exist
| `INVALID_TYPE` | Unknown element type
| `INVALID_POSITION` | Invalid insert position (must be "before", "after", or "append")
| `WRITE_FAILED` | Write operation failed (file permission, disk full, etc.)
|===

== Tool Summary

.Implemented MCP Tools
[cols="2,3"]
|===
| Tool | Description

| `get_structure` | Get hierarchical document structure
| `get_section` | Read content of a specific section
| `get_sections_at_level` | Get all sections at a nesting level
| `search` | Search documentation content
| `get_elements` | Get code blocks, tables, images, etc.
| `get_metadata` | Get project or section metadata
| `validate_structure` | Validate document structure
| `update_section` | Update section content
| `insert_content` | Insert content before/after sections
| `get_dependencies` | Get include dependencies
|===

.Planned Tools
[cols="2,3"]
|===
| Tool | Description

| `update_element` | Replace a specific element (code, table)
| `get_health` | Server health status
| `reindex` | Trigger manual reindexing
|===