You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat: add TOON output format for token-efficient LLM responses (#155)
Implement TOON (Token-Oriented Object Notation) as the default output format
for all Jira API responses, providing 30-60% token reduction compared to JSON.
Changes:
- Add @toon-format/toon package dependency
- Create toon.util.ts with TOON conversion logic and JSON fallback
- Add toOutputString function to jq.util.ts for format conversion
- Add outputFormat parameter to all tool types (toon/json)
- Update controller to respect outputFormat parameter (defaults to TOON)
- Add --output-format CLI option to all commands
- Update all tool descriptions with:
* TOON as default output format
* Cost optimization warnings (always use jq filter)
* Schema discovery pattern (fetch one item first to explore fields)
- Add comprehensive test coverage for TOON utilities
TOON conversion falls back to JSON if encoding fails, ensuring reliability.
Copy file name to clipboardExpand all lines: src/tools/atlassian.api.tool.ts
+33-6Lines changed: 33 additions & 6 deletions
Original file line number
Diff line number
Diff line change
@@ -125,7 +125,18 @@ function registerTools(server: McpServer) {
125
125
// Register the GET tool
126
126
server.tool(
127
127
'jira_get',
128
-
`Read any Jira data. Returns JSON, optionally filtered with JMESPath (\`jq\` param).
128
+
`Read any Jira data. Returns TOON format by default (30-60% fewer tokens than JSON).
129
+
130
+
**IMPORTANT - Cost Optimization:**
131
+
- ALWAYS use \`jq\` param to filter response fields. Unfiltered responses are very expensive!
132
+
- Use \`maxResults\` query param to restrict result count (e.g., \`maxResults: "5"\`)
133
+
- If unsure about available fields, first fetch ONE item with \`maxResults: "1"\` and NO jq filter to explore the schema, then use jq in subsequent calls
134
+
135
+
**Schema Discovery Pattern:**
136
+
1. First call: \`path: "/rest/api/3/search", queryParams: {"maxResults": "1", "jql": "project=PROJ"}\` (no jq) - explore available fields
137
+
2. Then use: \`jq: "issues[*].{key: key, summary: fields.summary, status: fields.status.name}"\` - extract only what you need
138
+
139
+
**Output format:** TOON (default, token-efficient) or JSON (\`outputFormat: "json"\`)
129
140
130
141
**Common paths:**
131
142
- \`/rest/api/3/project\` - list all projects
@@ -140,7 +151,7 @@ function registerTools(server: McpServer) {
Copy file name to clipboardExpand all lines: src/tools/atlassian.api.types.ts
+21-2Lines changed: 21 additions & 2 deletions
Original file line number
Diff line number
Diff line change
@@ -1,8 +1,20 @@
1
1
import{z}from'zod';
2
2
3
+
/**
4
+
* Output format options for API responses
5
+
* - toon: Token-Oriented Object Notation (default, more token-efficient for LLMs)
6
+
* - json: Standard JSON format
7
+
*/
8
+
exportconstOutputFormat=z
9
+
.enum(['toon','json'])
10
+
.optional()
11
+
.describe(
12
+
'Output format: "toon" (default, 30-60% fewer tokens) or "json". TOON is optimized for LLMs with tabular arrays and minimal syntax.',
13
+
);
14
+
3
15
/**
4
16
* Base schema fields shared by all API tool arguments
5
-
* Contains path, queryParams, and jq filter
17
+
* Contains path, queryParams, jq filter, and outputFormat
6
18
*/
7
19
constBaseApiToolArgs={
8
20
/**
@@ -33,13 +45,20 @@ const BaseApiToolArgs = {
33
45
34
46
/**
35
47
* Optional JMESPath expression to filter/transform the response
48
+
* IMPORTANT: Always use this to reduce response size and token costs
36
49
*/
37
50
jq: z
38
51
.string()
39
52
.optional()
40
53
.describe(
41
-
'JMESPath expression to filter/transform the JSON response. Examples: "issues[*].key" (extract keys), "total" (single field), "{key: key, summary: fields.summary}" (reshape object). See https://jmespath.org for syntax.',
54
+
'JMESPath expression to filter/transform the response. IMPORTANT: Always use this to extract only needed fields and reduce token costs. Examples: "issues[*].{key: key, summary: fields.summary}" (extract specific fields), "issues[0]" (first result), "issues[*].key" (keys only). See https://jmespath.org',
42
55
),
56
+
57
+
/**
58
+
* Output format for the response
59
+
* Defaults to TOON (token-efficient), can be set to JSON if needed
0 commit comments