Feature: Get document structure
As an LLM Client
I want to retrieve the hierarchical structure of a documentation project
To get an overview of available content
Background:
Given the server is started
And the project "test-docs" is indexed
And the project contains the following structure:
| Path | Title |
| introduction | 1. Introduction |
| introduction.goals | 1.1 Goals |
| introduction.scope | 1.2 Scope |
| constraints | 2. Constraints |
| constraints.technical | 2.1 Technical |
Scenario: Retrieve complete structure
When I call GET /structure
Then I receive HTTP Status 200
And the response contains all 5 sections
And the structure is hierarchically nested
Scenario: Retrieve structure with depth limit
When I call GET /structure?max_depth=1
Then I receive HTTP Status 200
And the response contains only sections of level 1
And "introduction" has no children
And "constraints" has no children
Scenario: Reject negative max_depth (Issue #220)
When I call GET /structure?max_depth=-1
Then I receive HTTP Status 400
And the error message contains "must be non-negative"
Scenario: Structure for empty project
Given the project contains no documents
When I call GET /structure
Then I receive HTTP Status 200
And the response contains an empty structure
And total_sections is 0
MCP Documentation Server - Acceptance Criteria
1. Overview
This document defines the acceptance criteria in Gherkin format (Given-When-Then). These scenarios can be used directly as a basis for automated tests.
2. Feature: Get Document Structure (UC-01)
3. Feature: Read Section (UC-02)
Feature: Read section
As an LLM Client
I want to read the content of a specific section
To access documentation content in a targeted manner
Background:
Given the server is started
And the project "test-docs" is indexed
And the section "introduction.goals" exists with content:
"""
== Goals
The main goals are:
* Goal 1
* Goal 2
"""
Scenario: Read existing section
When I call GET /section/introduction.goals
Then I receive HTTP Status 200
And the response contains the complete section content
And the field "path" is "introduction.goals"
And the field "format" is "asciidoc"
Scenario: Request non-existing section
When I call GET /section/nonexistent.path
Then I receive HTTP Status 404
And the error code is "PATH_NOT_FOUND"
And the error message contains "nonexistent.path"
Scenario: Read section with URL-encoded path
Given the section "chapter-1.section-2" exists
When I call GET /section/chapter-1.section-2
Then I receive HTTP Status 200
Scenario: Location information is correct
When I call GET /section/introduction.goals
Then the response contains a "location" object
And "location.file" is a relative file path
And "location.start_line" is greater than 0
And "location.end_line" is greater than or equal to "location.start_line"
4. Feature: Update Section (UC-03)
Feature: Update section
As an LLM Client
I want to update the content of a section
To maintain and improve documentation
Background:
Given the server is started
And the project "test-docs" is indexed
And the section "introduction.goals" exists
And the file system is writable
Scenario: Successfully update section
When I call PUT /section/introduction.goals with:
"""
{
"content": "== Goals\n\nUpdated goals content."
}
"""
Then I receive HTTP Status 200
And the field "success" is true
And the new content is saved in the file
And the index is updated
Scenario: Preserve title on update
Given the section has the title "1.1 Goals"
When I call PUT /section/introduction.goals with:
"""
{
"content": "New content without title",
"preserve_title": true
}
"""
Then I receive HTTP Status 200
And the title "1.1 Goals" is preserved
Scenario: Change section title with preserve_title false
Given the section has the title "1.1 Goals"
When I call PUT /section/introduction.goals with:
"""
{
"content": "=== New Title\n\nNew content with new title.",
"preserve_title": false
}
"""
Then I receive HTTP Status 200
And the title "New Title" is in the file
And the old title "1.1 Goals" is not in the file
Scenario: Reject update with preserve_title false when content has no title (Issue #195)
Given the section has the title "1.1 Goals"
When I call PUT /section/introduction.goals with:
"""
{
"content": "Content without a section title",
"preserve_title": false
}
"""
Then I receive HTTP Status 400
And the error message contains "must include a section title"
And the original file is unchanged
Scenario: Update non-existing section
When I call PUT /section/nonexistent with:
"""
{
"content": "Some content"
}
"""
Then I receive HTTP Status 404
And the error code is "PATH_NOT_FOUND"
Scenario: Atomic write operation on error
Given writing to the temporary file fails
When I call PUT /section/introduction.goals with:
"""
{
"content": "New content"
}
"""
Then I receive HTTP Status 500
And the error code is "WRITE_FAILED"
And the original file is unchanged
And no .tmp or .bak files remain
Scenario: Hash values for change tracking
When I call PUT /section/introduction.goals with valid content
Then the response contains "previous_hash"
And the response contains "new_hash"
And "previous_hash" differs from "new_hash"
5. Feature: Search Content (UC-04)
Feature: Search content
As an LLM Client
I want to search for content in the documentation project
To quickly find relevant information
Background:
Given the server is started
And the project "test-docs" is indexed
And the project contains sections with various content
Scenario: Successful search with matches
Given a section contains the text "atomic write operation"
When I call POST /search with:
"""
{
"query": "atomic write"
}
"""
Then I receive HTTP Status 200
And the result list contains at least 1 match
And each match has a "path"
And each match has a "context" with the search term
And each match has a "score" between 0 and 1
Scenario: Search without matches
When I call POST /search with:
"""
{
"query": "xyznonexistentterm"
}
"""
Then I receive HTTP Status 200
And the result list is empty
And "total_results" is 0
Scenario: Search with scope restriction
When I call POST /search with:
"""
{
"query": "performance",
"scope": "quality"
}
"""
Then I receive HTTP Status 200
And all matches have a path starting with "quality"
Scenario: Case-sensitive search
Given a section contains "Performance" but not "performance"
When I call POST /search with:
"""
{
"query": "performance",
"case_sensitive": true
}
"""
Then the result list does not contain the section with "Performance"
Scenario: Limit result count
Given there are more than 10 matches for "section"
When I call POST /search with:
"""
{
"query": "section",
"max_results": 5
}
"""
Then the result list contains at most 5 matches
Scenario: CLI warns for non-existent scope (Issue #226)
When I call dacli search "query" --scope nonexistent.path
Then the CLI displays a warning about the scope not found
And the search continues (may return empty results)
6. Feature: Filter Elements by Type (UC-05)
Feature: Filter elements by type
As an LLM Client
I want to retrieve elements of a specific type
To access diagrams, tables, or code in a targeted manner
Background:
Given the server is started
And the project "test-docs" is indexed
And the project contains:
| Type | Count |
| diagram | 5 |
| table | 8 |
| code | 12 |
Scenario: Retrieve all PlantUML diagrams
When I call GET /elements?type=plantuml
Then I receive HTTP Status 200
And the field "type" is "plantuml"
And "count" is 5
And each element has a "path"
And each element has a "location"
Scenario: Tables of a specific section
Given the section "quality.performance" contains 2 tables
When I call GET /elements?type=table&path=quality.performance
Then I receive HTTP Status 200
And "count" is 2
And all elements have path "quality.performance"
Scenario: Invalid element type
When I call GET /elements?type=charts
Then I receive HTTP Status 400
And the error code is "INVALID_TYPE"
And the response contains valid types
Scenario: Element type without matches
Given the project contains no images
When I call GET /elements?type=image
Then I receive HTTP Status 200
And "count" is 0
And "elements" is an empty array
Scenario: CLI warns for invalid element type (Issue #225)
When I call dacli elements --type charts
Then the CLI displays a warning about invalid type
And valid types are listed in the warning
And the result is empty (not an error)
7. Feature: Get Metadata (UC-06)
Feature: Get metadata
As an LLM Client
I want to retrieve metadata about the project or sections
To get information about scope and currency
Background:
Given the server is started
And the project "test-docs" is indexed
Scenario: Retrieve project metadata
When I call GET /metadata without path parameter
Then I receive HTTP Status 200
And the response contains "total_files"
And the response contains "total_sections"
And the response contains "total_words"
And the response contains "last_modified" in ISO 8601 format
Scenario: Retrieve section metadata
When I call GET /metadata?path=introduction
Then I receive HTTP Status 200
And the field "path" is "introduction"
And the response contains "word_count"
And the response contains "subsection_count"
Scenario: Metadata for non-existing path
When I call GET /metadata?path=nonexistent
Then I receive HTTP Status 404
8. Feature: Validate Structure (UC-07)
Feature: Validate structure
As an LLM Client
I want to check the document structure for consistency
To detect problems early
Background:
Given the server is started
And the project "test-docs" is indexed
Scenario: Check valid structure
Given the project has no structural problems
When I call POST /validate
Then I receive HTTP Status 200
And "valid" is true
And "errors" is an empty array
Scenario: Detect unresolved includes
Given the file "chapter.adoc" contains "include::missing.adoc[]"
And the file "missing.adoc" does not exist
When I call POST /validate
Then I receive HTTP Status 200
And "valid" is false
And "errors" contains an entry with type "unresolved_include"
Scenario: Detect circular includes
Given File A includes File B
And File B includes File A
When I call POST /validate
Then I receive HTTP Status 200
And "valid" is false
And "errors" contains an entry with type "circular_include"
Scenario: Orphaned files as warning
Given the file "orphan.adoc" is not included by any document
When I call POST /validate
Then I receive HTTP Status 200
And "warnings" contains an entry with type "orphaned_file"
9. Feature: Server Initialization (UC-08)
Feature: Server initialization
As a system
I must index the documentation project at startup
To enable fast queries
Scenario: Successful initialization
Given the project directory contains AsciiDoc files
When the server is started
Then the index is built after startup
And the health endpoint reports "index_ready": true
Scenario: Initialization with empty directory
Given the project directory is empty
When the server is started
Then the server starts with an empty index
And a warning is logged
Scenario: Fault-tolerant initialization
Given a file in the project is not parseable
When the server is started
Then the faulty file is skipped
And an error is logged
And the other files are indexed
Scenario: Include resolution during initialization
Given the main file includes three sub-files
When the server is started
Then all included sections are in the index
And the include relationships are captured
10. Feature: Insert Content (UC-09)
Feature: Insert content
As an LLM Client
I want to insert new content at a specific position
To extend documentation
Background:
Given the server is started
And the project "test-docs" is indexed
And the section "introduction" exists
Scenario: Insert content before a section
When I call POST /section/introduction/insert with:
"""
{
"position": "before",
"content": "== Preface\n\nThis is a preface."
}
"""
Then I receive HTTP Status 200
And the new content is before the section "introduction"
Scenario: Insert content after a section
When I call POST /section/introduction/insert with:
"""
{
"position": "after",
"content": "== Summary\n\nThis is a summary."
}
"""
Then I receive HTTP Status 200
And the new content is after the section "introduction"
Scenario: Insert after includes all child sections (Issue #229)
Given the section "parent" has child sections "parent.child1" and "parent.child2"
When I call POST /section/parent/insert with:
"""
{
"position": "after",
"content": "== New Section\n\nContent."
}
"""
Then I receive HTTP Status 200
And the new content is after "parent.child2"
And the new content is before the next sibling of "parent"
Scenario: Append content to section
When I call POST /section/introduction/insert with:
"""
{
"position": "append",
"content": "\n\nAdditional paragraph."
}
"""
Then I receive HTTP Status 200
And the new content is at the end of the section "introduction"
Scenario: Invalid position
When I call POST /section/introduction/insert with:
"""
{
"position": "invalid",
"content": "Some content"
}
"""
Then I receive HTTP Status 400
And the error code is "INVALID_POSITION"
11. Feature: Replace Element (UC-10)
Feature: Replace element
As an LLM Client
I want to replace a specific element within a section
To update tables, code blocks, or diagrams in a targeted manner
Background:
Given the server is started
And the project "test-docs" is indexed
And the section "quality.performance" contains a table at index 0
Scenario: Successfully replace table
When I call PUT /element/quality.performance/0 with:
"""
{
"content": "[cols=\"1,2\"]\n|===\n| New | Table\n|==="
}
"""
Then I receive HTTP Status 200
And "success" is true
And the table in the file is updated
Scenario: Element at invalid index
When I call PUT /element/quality.performance/99 with:
"""
{
"content": "New content"
}
"""
Then I receive HTTP Status 404
And the error code is "ELEMENT_NOT_FOUND"
Scenario: Element in non-existing section
When I call PUT /element/nonexistent/0 with:
"""
{
"content": "New content"
}
"""
Then I receive HTTP Status 404
And the error code is "PATH_NOT_FOUND"
12. Feature: Non-Functional Requirements
Feature: Performance requirements
As a system
I must meet certain performance criteria
Scenario: Fast response times for read operations
Given a project with 600 pages is indexed
When I call GET /section/some.path
Then the response time is under 2 seconds
Scenario: Acceptable indexing time
Given a project with 600 pages
When the server is started
Then indexing is completed in under 60 seconds
Scenario: Low idle resource consumption
Given the server is started and idle
When no requests come in for 60 seconds
Then CPU utilization is under 5%
And memory consumption is stable
Feature: Reliability requirements
As a system
I must ensure data integrity
Scenario: Atomic write operations
Given a write operation is in progress
When an error occurs during writing
Then the original file is unchanged
And no temporary files remain
Scenario: Graceful error handling
Given a file is not readable
When I call GET /section/path.to.file
Then I receive HTTP Status 500
And the error message is informative
And the server remains stable
13. Traceability Matrix
| Use Case | API Endpoints | Acceptance Scenarios |
|---|---|---|
UC-01 |
GET /structure, GET /sections |
3 scenarios |
UC-02 |
GET /section/{path} |
4 scenarios |
UC-03 |
PUT /section/{path} |
5 scenarios |
UC-04 |
POST /search |
5 scenarios |
UC-05 |
GET /elements |
4 scenarios |
UC-06 |
GET /metadata, GET /dependencies |
3 scenarios |
UC-07 |
POST /validate |
4 scenarios |
UC-08 |
(System Startup) |
4 scenarios |
UC-09 |
POST /section/{path}/insert |
4 scenarios |
UC-10 |
PUT /element/{path}/{index} |
3 scenarios |
14. Appendix: Test Data Specification
14.1. Minimal Test Project
test-docs/
├── arc42.adoc # Main document with includes
├── chapters/
│ ├── 01_introduction.adoc
│ ├── 02_constraints.adoc
│ └── 03_context.adoc
└── images/
└── diagram.png
14.2. Structure of Test Documents
// arc42.adoc
= Test Documentation
include::chapters/01_introduction.adoc[]
include::chapters/02_constraints.adoc[]
include::chapters/03_context.adoc[]
// chapters/01_introduction.adoc
== Introduction
=== Goals
The goals are...
=== Scope
The scope includes...
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.