cd /news/ai-agents/from-30-tools-to-3-designing-a-token… Β· home β€Ί topics β€Ί ai-agents β€Ί article
[ARTICLE Β· art-98339] src=dev.to β†— pub= topic=ai-agents verified=true sentiment=Β· neutral

From 30 Tools to 3: Designing a Token-Efficient MCP Tool Surface

A developer describes a pattern for reducing large MCP tool surfaces into a few domain-oriented tools by using an 'action' discriminator, which preserves capabilities while shrinking the model's context and decision space. The approach consolidates tools like Jira, GitLab, and Confluence into 3-5 domain tools, improving token efficiency and agent performance.

read16 min views1 publishedAug 15, 2026

Modern agentic applications rarely suffer from a lack of tools.

They suffer from too many of them.

As an AI agent grows, it is common to connect it to Jira, GitLab, Confluence, Sentry, Elasticsearch, Jaeger, databases, monitoring systems, internal APIs, deployment platforms, and dozens of other services.

Each integration can expose many operations:

Jira
β”œβ”€β”€ searchIssues
β”œβ”€β”€ getIssue
β”œβ”€β”€ createIssue
β”œβ”€β”€ updateIssue
β”œβ”€β”€ addComment
β”œβ”€β”€ transitionIssue
β”œβ”€β”€ getTransitions
β”œβ”€β”€ assignIssue
└── ...

GitLab
β”œβ”€β”€ listProjects
β”œβ”€β”€ getProject
β”œβ”€β”€ listIssues
β”œβ”€β”€ createIssue
β”œβ”€β”€ updateIssue
β”œβ”€β”€ listMergeRequests
β”œβ”€β”€ getMergeRequest
β”œβ”€β”€ createComment
└── ...

Confluence
β”œβ”€β”€ searchPages
β”œβ”€β”€ getPage
β”œβ”€β”€ createPage
β”œβ”€β”€ updatePage
└── ...

It is easy to end up with 30, 50, or even hundreds of tools.

At first, this looks like a capability problem.

It is actually a tool-surface problem.

The agent does not necessarily need fewer capabilities.

It needs fewer top-level tools.

This article describes a pattern I have been using to reduce large MCP/tool surfaces into a small number of domain-oriented tools while preserving the underlying capabilities.

The core idea is simple:

Consolidate the tool surface, not the capabilities.

Instead of exposing:

30 MCP tools

we can expose:

3–5 domain tools

and use an action

discriminator to route requests internally.

For example:

jira_search
jira_get_issue
jira_create_issue
jira_update_issue
jira_add_comment
jira_transition_issue
...

can become:

jira({
  action: "search",
  ...
})

jira({
  action: "getIssue",
  ...
})

jira({
  action: "createIssue",
  ...
})

The backend still has all the original capabilities.

The model simply sees a much smaller tool surface.

An MCP server is not only an execution interface.

It is also part of the model's context.

When an agent connects to an MCP server, the model generally needs to understand:

Imagine an agent connected to 40 tools.

Even if each tool has a relatively small schema, the aggregate context can become significant.

More importantly, the model now has a larger decision space:

User request
     β”‚
     β–Ό
Which tool?
     β”‚
 β”Œβ”€β”€β”€β”Όβ”€β”€β”€β”€β”¬β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”
 β–Ό   β–Ό    β–Ό    β–Ό    β–Ό    β–Ό
T1   T2   T3   T4   T5   ...

The model has to distinguish between many semantically related operations.

For example:

jira_search_issues
jira_search_projects
jira_get_issue
jira_get_issue_comments
jira_get_issue_transitions
jira_get_issue_worklogs

are all part of the same conceptual domain.

There is little value in forcing the model to treat every operation as a completely independent top-level capability.

The pattern is to introduce an intermediate discriminator:

{
  "action": "search",
  "query": "authentication bug"
}

Instead of:

jira_search

we expose:

jira

The tool becomes a small router.

Conceptually:

                     jira
                      β”‚
                 action field
                      β”‚
       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
       β–Ό              β–Ό              β–Ό
    search         getIssue       createIssue
       β”‚              β”‚              β”‚
       β–Ό              β–Ό              β–Ό
 searchHandler   issueHandler   createHandler

The important point is that the tool is not the capability.

The tool is the external interface.

The action represents the capability.

This gives us:

30 capabilities
       ↓
3 domain-oriented tools

without throwing away functionality.

The easiest mistake is to think:

"I have 30 tools, so I will put 10 operations into each tool."

That is not the goal.

Grouping should follow semantic domains.

For example:

jira
β”œβ”€β”€ search
β”œβ”€β”€ issue
β”œβ”€β”€ comment
β”œβ”€β”€ transition
└── project

gitlab
β”œβ”€β”€ project
β”œβ”€β”€ issue
β”œβ”€β”€ mergeRequest
└── pipeline

observability
β”œβ”€β”€ search
β”œβ”€β”€ trace
β”œβ”€β”€ log
└── error

The exact grouping depends on the integration.

For a database:

db_tables
db_query
db_advanced

might make sense.

For Jira:

jira_issues
jira_projects
jira_search

may be better.

For GitLab:

gitlab_repository
gitlab_issues
gitlab_mergeRequests

may be more natural.

There is no universal number.

The goal is to find the smallest tool surface that still preserves clear semantic boundaries.

A database integration is a useful example because database APIs can easily expose a large number of operations.

Instead of:

listTables
getTableSchema
getSampleData
getTableSize
executeQuery
getDatabaseInfo
listRelationships
getIndexes
profileColumn
searchSchema
listProcedures
getTriggers
compareSchemas

we can expose:

db_tables
db_query
db_advanced

The first tool can use:

const tablesSchema = z.discriminatedUnion("action", [
  z.object({
    action: z.literal("list"),
    schema: schemaField,
  }),

  z.object({
    action: z.literal("schema"),
    tableName: z.string(),
    schema: schemaField,
  }),

  z.object({
    action: z.literal("sampleData"),
    tableName: z.string(),
    schema: schemaField,
    rowCount: z.number().optional().default(10),
  }),

  z.object({
    action: z.literal("size"),
    tableName: z.string(),
    schema: schemaField,
  }),
]);

The model sees one tool:

db_tables

with an explicit action space:

list
schema
sampleData
size

The runtime still has four separate handlers.

switch (args.action) {
  case "list":
    return handleListTables(args.schema);

  case "schema":
    return handleGetTableSchema(
      args.tableName,
      args.schema
    );

  case "sampleData":
    return handleGetSampleData(
      args.tableName,
      args.schema,
      args.rowCount
    );

  case "size":
    return handleGetTableSize(
      args.tableName,
      args.schema
    );
}

This distinction is important:

Consolidation happens at the MCP interface, not inside the business logic.

The internal handlers remain independently testable and maintainable.

For TypeScript applications, z.discriminatedUnion()

provides a clean way to express this pattern.

For example:

const querySchema = z.discriminatedUnion("action", [
  z.object({
    action: z.literal("execute"),
    query: z.string(),
    params: z.record(z.string()).optional(),
    limit: z.number().optional().default(100),
  }),

  z.object({
    action: z.literal("info"),
  }),
]);

The type can then be inferred directly:

type QueryInput = z.infer<typeof querySchema>;

This gives us three useful properties:

The resulting architecture becomes:

             MCP Tool
                β”‚
                β–Ό
        Discriminated Union
                β”‚
          β”Œβ”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”
          β”‚  action   β”‚
          β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜
                β”‚
       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”
       β–Ό        β–Ό        β–Ό
    Handler A Handler B Handler C
       β”‚        β”‚        β”‚
       β””β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”˜
                β–Ό
             Backend

This is much more predictable than asking the model to navigate dozens of unrelated top-level tools.

This is probably the most important conceptual distinction.

Suppose we have:

3 tools
13 actions

That does not mean we lost 10 capabilities.

We have:

3 external interfaces
13 internal capabilities

Therefore:

Tool count β‰  capability count

This distinction becomes increasingly important as agent systems grow.

A large organization may have:

Jira             20 operations
GitLab            25 operations
Confluence        15 operations
Sentry             8 operations
ELK               10 operations
Jaeger             6 operations
Database           20 operations

That can easily become 100+ operations.

Exposing all of them directly to the model creates an unnecessarily large tool surface.

Instead, we can build:

jira
gitlab
confluence
sentry
observability
database

and keep the underlying operation count unchanged.

The primary optimization is reducing the amount of tool metadata the model needs to process.

Instead of presenting:

Tool 1
Tool 2
Tool 3
Tool 4
...
Tool 30

we present:

Tool A
Tool B
Tool C

This can reduce:

However, this should not be described as a guaranteed linear cost reduction.

If we transform:

30 tools β†’ 3 tools

it does not necessarily mean:

90% lower token cost

because the consolidated schemas themselves can become larger.

The correct statement is:

Tool consolidation can significantly reduce the tool metadata exposed to the model, but the actual token and latency savings depend on schema size, descriptions, provider behavior, and how the agent framework handles tools.

This distinction matters.

There is an important trade-off.

Consider a tool with 40 actions:

enterprise({
  action: ...
})

with actions such as:

createCustomer
deleteCustomer
searchInvoice
rotateCredentials
deployService
createRepository
getTrace
searchLogs
...

This is technically possible.

It is also terrible design.

The model now has one enormous schema.

The problem has simply moved from:

30 tools

to:

1 giant tool

The correct approach is domain-oriented consolidation.

For example:

customer
billing
repository
observability
deployment

The ideal number might be 5 rather than 1.

Therefore:

Minimize the tool surface, but do not minimize it blindly.

Once multiple capabilities share one tool, the action

field becomes extremely important.

Bad:

action: z.string()

Better:

action: z.enum([
  "search",
  "get",
  "create",
  "update"
])

Best, when actions have different parameters:

z.discriminatedUnion("action", [
  searchSchema,
  getSchema,
  createSchema,
  updateSchema,
])

Now the action and its parameters form a strongly typed relationship.

For example:

action = "search"
β†’ query required

action = "get"
β†’ issueId required

action = "create"
β†’ title + description required

This is much more expressive than one generic schema with dozens of optional fields.

In practice, there is another layer of complexity.

MCP tool schemas ultimately need to be represented as JSON Schema.

A Zod discriminated union can produce a schema based on:

{
  "anyOf": [...]
}

or:

{
  "oneOf": [...]
}

depending on the converter.

Some MCP schema handling paths expect an object at the root.

That creates a compatibility problem.

In one implementation, the MCP SDK's Zod compatibility layer expected an object shape and did not naturally handle the discriminated union in the same way.

A compatibility layer can therefore normalize the generated schema.

Conceptually:

Zod discriminated union
          β”‚
          β–Ό
     JSON Schema
          β”‚
          β–Ό
   MCP normalization
          β”‚
          β–Ό
MCP-compatible object schema

The important architectural principle is:

Adapt the schema exposed to the model without weakening the runtime validator.

The original Zod schema should remain the source of truth for validation.

This leads to an important distinction.

There are effectively two concerns:

LLM-facing representation
        β”‚
        β–Ό
Tool selection and argument generation

Runtime representation
        β”‚
        β–Ό
Validation and execution

The LLM-facing schema needs to be:

The runtime schema needs to be:

These do not necessarily have to be identical.

For example, a flattened object representation may make action choices easier for a model to see, while the original discriminated union remains responsible for strict validation.

This is a useful general principle for agent infrastructure:

Optimize schemas for model consumption, but never use model-facing schemas as the only security boundary.

When there are 30 tools, each tool can have a very specific description.

When there are 3 tools, the description needs to explain the action space.

For example:

Unified tool for advanced database analysis.

ACTIONS:

relationships
  List foreign key relationships.

indexes
  Get indexes for a table.

profileColumn
  Analyze nullability, cardinality and top values.

searchSchema
  Search tables and columns.

listProcedures
  List stored procedures.

triggers
  Get triggers.

compareSchemas
  Compare two table definitions.

This is not documentation only.

It is part of the model's routing interface.

A useful mental model is:

Tool name
    +
Description
    +
Action enum
    +
Parameter schema
        ↓
Agent routing signal

Therefore, when consolidating tools, descriptions should become more intentional, not less.

This approach becomes much more valuable when applied across an entire engineering environment.

Instead of:

searchIssues
getIssue
createIssue
updateIssue
addComment
transitionIssue
assignIssue
getTransitions

use:

jira_issues

with:

search
get
create
update
comment
transition
assign

Instead of exposing every repository, issue, merge request and pipeline operation:

gitlab_repository
gitlab_issues
gitlab_mergeRequests
gitlab_pipelines

Each can expose a focused action set.

Instead of:

searchPages
getPage
createPage
updatePage
deletePage
getChildren

use:

wiki

with:

search
get
create
update
children

Potentially:

sentry

with:

searchIssues
getIssue
events
releases
projects

Potentially:

logs

with:

search
aggregate
fields
indices

Potentially:

tracing

with:

search
getTrace
services
operations

The important point is not the exact names.

It is the architectural pattern.

One of the most practical aspects of this approach is that we do not necessarily need to rewrite every integration.

There are already MCP implementations for many popular systems.

The problem is that their exposed tool surface may not be optimal for a specific agent.

Instead of:

Agent
  β”‚
  β”œβ”€β”€ 20 Jira tools
  β”œβ”€β”€ 20 GitLab tools
  └── 15 Confluence tools

we can introduce a customized layer:

                 Agent
                   β”‚
             Custom MCP Layer
                   β”‚
        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
        β–Ό          β–Ό          β–Ό
      Jira       GitLab    Confluence
        β”‚          β”‚          β”‚
     existing   existing   existing
       APIs       MCP        MCP

The custom layer becomes an agent-oriented facade.

This is particularly useful when the existing integration is technically correct but exposes too many low-level operations.

This suggests a broader architectural pattern.

Traditional integration:

Agent β†’ MCP β†’ Service

Customized integration:

Agent
  ↓
Agent-oriented MCP facade
  ↓
Service-specific MCP/API
  ↓
Service

The facade can provide:

The MCP layer therefore becomes more than a transport.

It becomes an agent interface layer.

There is an important security implication.

If we consolidate:

jira_create
jira_update
jira_delete

into:

jira({
  action: ...
})

we should not simply grant:

permission: jira

and assume all operations are equivalent.

Permissions should still be evaluated at the action level.

For example:

jira.search       β†’ allowed
jira.get          β†’ allowed
jira.create       β†’ allowed
jira.update       β†’ approval required
jira.delete       β†’ denied

The unified tool is only an interface optimization.

It must not become a security boundary that accidentally grants excessive privileges.

With consolidated tools, logging only the tool name is no longer sufficient.

Bad:

tool = jira

Better:

{
  "tool": "jira",
  "action": "search",
  "duration_ms": 142
}

Even better:

{
  "tool": "jira",
  "action": "search",
  "status": "success",
  "duration_ms": 142,
  "request_id": "...",
  "agent_id": "...",
  "user_id": "..."
}

The fundamental execution unit becomes:

tool + action

rather than just:

tool

This is particularly important for debugging agent behavior.

Tool consolidation should happen at the boundary.

Do not create a 2,000-line function like:

async function jira(args) {
  // everything
}

Instead:

async function jira(args: JiraInput) {
  switch (args.action) {
    case "search":
      return searchIssues(args);

    case "get":
      return getIssue(args);

    case "create":
      return createIssue(args);

    case "update":
      return updateIssue(args);
  }
}

Each handler remains independently testable:

jira()
  β”‚
  β”œβ”€β”€ searchIssues()
  β”œβ”€β”€ getIssue()
  β”œβ”€β”€ createIssue()
  └── updateIssue()

This preserves maintainability while reducing the external tool surface.

A practical rule for deciding whether two operations should be consolidated is:

Would a human developer naturally describe these operations as belonging to the same capability?

For example:

Jira search
Jira get issue
Jira update issue

Yes.

But:

Jira update issue
Elasticsearch search logs
Create AWS infrastructure

No.

Another useful test:

Would the same context usually be required to decide between these operations?

If yes, consolidation is often beneficial.

If no, keep them separate.

There are cases where separate tools are better.

database
payments
infrastructure
email

should not become:

enterprise({
  action: ...
})

If a single tool has 50 actions, the schema itself may become expensive and confusing.

Operations such as:

deleteProductionData
rotateCredentials
deployProduction

may deserve separate permission boundaries even if they belong to the same domain.

Read-only operations and destructive operations can sometimes benefit from separate interfaces:

jira_read
jira_write

instead of one enormous tool.

Again, there is no universal rule.

The goal is not:

30 β†’ 1

The goal is:

30 β†’ smallest useful semantic surface

For one system that might be:

30 β†’ 3

For another:

30 β†’ 7

For another:

30 β†’ 12

The optimization target is:

minimize unnecessary tool metadata

while preserving:

semantic clarity
validation
security
maintainability

A scalable implementation can look like this:

                        Agent
                          β”‚
                          β–Ό
                β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                β”‚  Agent MCP Layer β”‚
                β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                         β”‚
          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
          β–Ό              β–Ό              β–Ό
        jira           gitlab          wiki
          β”‚              β”‚              β”‚
     β”Œβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”
     β–Ό    β–Ό    β–Ό    β–Ό    β–Ό    β–Ό    β–Ό    β–Ό    β–Ό
  search get create issues MR pipeline search get update
          β”‚              β”‚              β”‚
          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                         β–Ό
                 Existing APIs/MCPs

The agent sees a compact interface.

The integration layer retains the full capability set.

MCP is often treated as:

"Expose every API operation as a tool."

That is a reasonable starting point.

For production agent systems, however, a better question is:

What interface should the model see?

Those are not necessarily the same thing.

A REST API might expose:

GET /issues
GET /issues/:id
POST /issues
PATCH /issues/:id
POST /issues/:id/comments
POST /issues/:id/transition

We do not have to expose every HTTP endpoint as a separate model-facing tool.

The MCP layer can become a semantic abstraction over those endpoints.

This is similar to designing an API specifically for a consumer rather than simply mirroring an underlying database or service API.

Traditional API design asks:

What endpoints does the system provide?

Agent interface design asks:

What decisions does the model need to make?

These are different questions.

A human developer may prefer:

getIssue
getIssueComments
getIssueTransitions
getIssueWorklogs

because each API operation is explicit.

An agent may perform better with:

jira_issue({
  action: "get",
  ...
})

and:

jira_issue({
  action: "comments",
  ...
})

because the model first identifies the domain and then chooses the operation.

This creates a two-level routing model:

Domain
  ↓
Action
  ↓
Arguments

rather than:

One large global tool-selection problem

The pattern can be generalized with TypeScript:

const toolSchema = z.discriminatedUnion("action", [
  searchSchema,
  getSchema,
  createSchema,
  updateSchema,
]);

server.registerTool(
  "jira",
  {
    description: "...",
    inputSchema: toolSchema,
  },
  async (args) => {
    switch (args.action) {
      case "search":
        return search(args);

      case "get":
        return get(args);

      case "create":
        return create(args);

      case "update":
        return update(args);
    }
  }
);

The implementation remains simple.

The important engineering work is deciding:

Tool consolidation should be measurable.

Before:

Tools: 32
Tool schema tokens: X
Average tool-selection latency: Y
Tool-selection errors: Z

After:

Tools: 5
Tool schema tokens: X'
Average tool-selection latency: Y'
Tool-selection errors: Z'

The most useful metrics include:

The objective is not merely:

fewer tools

but:

better agent performance per unit of context

This approach can be generalized beyond MCP.

The same principle applies to:

The pattern is essentially:

Traditional API
       ↓
Many low-level operations
       ↓
Agent-oriented facade
       ↓
Small semantic tool surface
       ↓
Action routing
       ↓
Strict execution layer

This is not really a database trick.

It is an agent interface design pattern.

The final mental model is simple:

                 β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                 β”‚      30 APIs         β”‚
                 β”‚    capabilities      β”‚
                 β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                            β”‚
                     Consolidation
                            β”‚
                            β–Ό
                 β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                 β”‚      3–5 tools       β”‚
                 β”‚  semantic domains    β”‚
                 β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                            β”‚
                     Action routing
                            β”‚
                            β–Ό
                 β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                 β”‚    30 handlers       β”‚
                 β”‚  original abilities β”‚
                 β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

The important transformation is therefore not:

30 capabilities β†’ 3 capabilities

It is:

30 exposed tools β†’ 3 exposed interfaces

The capabilities remain.

The model-facing surface becomes smaller.

As agent systems become more integrated, the number of available tools will continue to grow.

Jira, GitLab, Confluence, Sentry, ELK, Jaeger, databases, cloud platforms and internal systems can easily produce dozens or hundreds of operations.

Exposing every operation directly to the model is not always the best architecture.

A better approach is to introduce an agent-oriented tool layer:

Many low-level operations
          ↓
Semantic domain grouping
          ↓
Discriminated action schemas
          ↓
Small MCP tool surface
          ↓
Strict runtime validation
          ↓
Original capabilities

The central principle is:

Reduce the number of tools the model has to understand, not the number of capabilities your system provides.

A 30-tool integration does not necessarily need 30 model-facing tools.

It may need three well-designed interfaces with clear action spaces.

And this pattern becomes especially powerful when existing MCP servers are treated not as untouchable interfaces, but as underlying integrations that can be wrapped, adapted and optimized for the needs of the agent.

The future of MCP design may therefore be less about exposing everything an API can do, and more about designing the smallest useful interface through which an agent can do what it needs to do.

── more in #ai-agents 4 stories Β· sorted by recency
── more on @jira 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain β€” perfect for shipping the agent you just read about.

$git push zahid main
β†’ Live at https://your-agent.zahid.host βœ“
Get free account β†’ Pricing
from €0/mo Β· no card required
LIVE [news/from-30-tools-to-3-d…] indexed:0 read:16min 2026-08-15 Β· β€”