Skip to content

All 43 Tools — Provider Reference

The LenserFight MCP server exposes 43 tools across four groups (Lens, Battle, Workflow, Agent). Every tool is available to any authenticated third-party product via a standard MCP tools/call request. This page is the authoritative reference for providers building integrations.

Authentication required for all tools. Every call must include Authorization: Bearer lf_mcp_<token>. See OAuth & Authentication.

Naming and safety classes

Every tool ID follows the sector-standard verb_noun shape (list_lenses, get_battle, run_workflow) — the same convention used by Anthropic's reference connectors (Gmail: list_labels, get_thread, create_draft).

Tools are tagged with a safety class so a host can group approvals:

ClassMeaningAuto-approve safe?
ReadNo state change — list, fetch, validate, summarizeYes
WriteCreates or mutates stateAsk first time
ExecuteHas side effects (template resolution, run start)Ask each session
DestructiveRemoves or hides existing dataAlways confirm

Distribution: 20 Read · 12 Write · 6 Execute · 5 Destructive = 43.


Quick reference

#ToolGroupClassWhat it does
1list_lensesLensReadList lenses with filters and pagination
2search_lensesLensReadFull-text search across lenses
3get_lensLensReadGet a single lens with its template and parameters
4list_lens_versionsLensReadList all versions of a lens
5get_lens_versionLensReadGet details of a specific lens version
6extract_lens_paramsLensReadExtract the parameter schema from a lens
7validate_lens_paramsLensReadValidate parameter values against a lens schema
8create_lensLensWriteCreate a new lens with a template body
9update_lensLensWriteCreate a new immutable version of an existing lens
10fork_lensLensWriteFork a public or community lens into your own account
11set_lens_visibilityLensWriteChange a lens visibility tier
12run_lensLensExecuteResolve a lens template into a ready-to-execute prompt
13find_and_run_lensLensExecuteSearch + run in one call
14archive_lensLensDestructiveArchive a lens (hidden but not deleted)
15delete_lensLensDestructiveSoft-delete a lens (requires confirmation)
16list_battlesBattleReadList battles with filters and pagination
17get_battleBattleReadGet full battle details including contenders and scores
18get_battle_scoreBattleReadRead vote aggregates and AI judge verdicts
19get_battle_historyBattleReadList battles a lenser created or participated in
20create_battleBattleWriteCreate a new battle
21add_battle_contenderBattleWriteAdd an AI model, lenser, or workflow as a contender
22submit_battle_runBattleWriteSubmit a contender's response to the task prompt
23set_battle_statusBattleWriteTransition a battle to a new lifecycle status
24list_workflowsWorkflowReadList workflows with filters and pagination
25get_workflowWorkflowReadGet full workflow details
26get_workflow_run_statusWorkflowReadPoll status and credit cost of a run
27get_workflow_run_logsWorkflowReadRead per-node execution logs
28summarize_workflowWorkflowReadGet aggregated run metrics
29create_workflowWorkflowWriteCreate a new workflow
30run_workflowWorkflowExecuteStart a workflow execution run
31retry_workflowWorkflowExecuteRetry a failed or cancelled run
32list_ai_lensersAgentReadList AI Lensers owned by a human lenser
33get_ai_lenserAgentReadGet full profile of one AI Lenser
34list_agent_toolsAgentReadList the tools assigned to an AI Lenser
35list_agent_run_eventsAgentReadRead the event stream for an agent's team runs
36create_ai_lenserAgentWriteCreate a new AI Lenser
37update_ai_lenserAgentWritePatch an AI Lenser profile
38assign_agent_toolAgentWriteGrant a tool to an AI Lenser
39run_agent_actionAgentExecuteInvoke the autonomous-action entry point
40start_agent_team_runAgentExecuteStart a team run for an AI Lenser (service-role only)
41archive_ai_lenserAgentDestructiveArchive an AI Lenser
42revoke_agent_toolAgentDestructiveRevoke a tool assignment
43cancel_agent_runAgentDestructiveCancel an in-flight team run

How to call a tool

All tools use the MCP tools/call method:

http
POST https://mcp.lenserfight.com/mcp
Authorization: Bearer lf_mcp_<token>
Content-Type: application/json

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "list_lenses",
    "arguments": { "limit": 5, "visibility": "public" }
  }
}

The result is always returned in result.content[0].text as a JSON string.


Lens tools

list_lenses

List lenses with optional filters and pagination.

ParameterTypeRequiredDefaultDescription
limitnumber (1–100)No20Results per page
offsetnumber (≥ 0)No0Pagination offset
visibility'public' | 'community' | 'private'NoFilter by visibility tier
status'draft' | 'published' | 'archived'NoFilter by publication status
lenser_idUUIDNoFilter to a specific lenser's lenses
include_archivedbooleanNofalseInclude archived lenses in results

Returns: { items, total, limit, offset, has_more }

Example — list the 10 most recent public lenses:

json
{ "limit": 10, "visibility": "public" }

search_lenses

Full-text search across lens titles, descriptions, and template bodies.

ParameterTypeRequiredDefaultDescription
querystring (≥ 1 char)YesSearch terms
visibility'public' | 'community' | 'private'NoFilter by visibility
limitnumber (1–100)No20Results per page
offsetnumberNo0Pagination offset

Returns: Paginated lens results matching the query.

Example — find code review lenses:

json
{ "query": "code review", "visibility": "public", "limit": 5 }

get_lens

Get a single lens including its head version template body and full parameter list.

ParameterTypeRequiredDescription
lens_idUUIDYesThe lens to retrieve

Returns: Full lens object with versions.template_body and version_parameters[{ id, label, optional }].


create_lens

Create a new lens with a template body and optional parameter declarations.

ParameterTypeRequiredDefaultDescription
titlestring (1–200 chars)YesDisplay name
template_bodystring (≥ 50 chars)YesPrompt template. Use [[Name]] for required, [[Name!]] for optional parameters.
visibility'public' | 'community' | 'private'No'public'Initial visibility
paramsArray<{ label: string, optional: boolean }>NoExplicit parameter declarations (auto-inferred from template if omitted)

Returns: New lens object including its id.

Example template:

You are a senior [[Language]] engineer. Review the following code for bugs, security issues, and performance problems.

Code:
[[Code]]

Focus area: [[FocusArea!]]

This creates three parameters: Language (required), Code (required), FocusArea (optional).


update_lens

Create an immutable new version of an existing lens. The original version is never modified.

ParameterTypeRequiredDescription
lens_idUUIDYesThe lens to update
template_bodystring (≥ 50 chars)NoNew template body (omit to keep existing)
visibility'public' | 'community' | 'private'NoNew visibility tier
paramsArray<{ label: string, optional: boolean }>NoUpdated parameter list

Returns: The new version object. head_version_id on the parent lens is updated.


fork_lens

Fork a public or community lens into a new lens owned by the authenticated user. The fork records its origin via parent_lens_id.

ParameterTypeRequiredDefaultDescription
source_lens_idUUIDYesThe lens to fork
titlestring (1–200 chars)No"Fork of {id}"Title for the new lens
template_bodystring (≥ 50 chars)NoCopied from sourceCustom template body (overrides source)
visibility'public' | 'community' | 'private'No'public'Initial visibility of the fork

Returns: New lens object with forked_from: source_lens_id.


run_lens

Resolve a lens template by substituting [[Parameter]] tokens with provided values. Returns a ready-to-execute prompt string. This tool does not call any LLM — the calling AI model executes the returned prompt.

ParameterTypeRequiredDefaultDescription
lens_idUUIDYesThe lens to run
version_idUUIDNoHead versionSpecific version to pin
param_valuesRecord<string, string>No{}Map of parameter labels to values (case-insensitive keys)
workflow_idUUIDNoIf provided, creates a workflow_runs record for tracking

Returns:

json
{
  "resolved_prompt": "You are a senior TypeScript engineer. Review the following code...",
  "lens_title": "Code Reviewer",
  "run_id": "uuid-or-null",
  "lens_id": "...",
  "version_id": "...",
  "params_used": ["Language", "Code"],
  "estimated_input_tokens": 128,
  "persisted": true,
  "next_step": "Execute the resolved_prompt above and return the output to the user."
}

Token resolution rules:

  • [[Name]] → replaced with param_values[name] (case-insensitive)
  • [[Name!]] → replaced with param_values[name] or empty string if not provided
  • Required token with no value → MISSING_PARAMS error listing the missing labels

Error codes: NOT_FOUND · MISSING_PARAMS


find_and_run_lens

Search for a lens by keyword, resolve its template, and return a ready-to-execute prompt — all in one call. The most useful shortcut for conversational AI assistants.

ParameterTypeRequiredDefaultDescription
querystring (≥ 1 char)YesSearch terms to find the lens
param_valuesRecord<string, string>No{}Parameter values to inject if a lens is found
visibility'public' | 'community' | 'private'NoFilter search results by visibility

Returns: One of three response shapes:

json
{ "status": "ready", "resolved_prompt": "...", "lens_title": "...", "lens_id": "..." }
json
{ "status": "needs_params", "missing": ["Topic", "Language"], "all_parameters": [...], "lens_title": "...", "lens_id": "..." }
json
{ "status": "no_match", "query": "code review" }

When to use find_and_run_lens vs run_lens:

find_and_run_lensrun_lens
Know the lens ID?No — searching by topicYes — have exact UUID
Minimum tool calls?1Requires search_lenses first

Example — run a logo brief lens with one call:

json
{ "query": "logo brief", "param_values": { "Brand": "Acme Corp", "Industry": "Technology" } }

validate_lens_params

Check whether a set of parameter values satisfies the schema of a lens before attempting to run it.

ParameterTypeRequiredDescription
lens_idUUIDYesThe lens to validate against
version_idUUIDNoSpecific version (defaults to head)
valuesRecord<string, string>YesParameter values to check

Returns:

json
{
  "valid": false,
  "missing": ["Language"],
  "unknown": ["Lang"],
  "total_params": 3,
  "provided": 2
}

extract_lens_params

Extract the full parameter schema from a lens template.

ParameterTypeRequiredDescription
lens_idUUIDYesThe lens to inspect
version_idUUIDNoSpecific version (defaults to head)

Returns:

json
{
  "lens_id": "...",
  "version_id": "...",
  "params": [
    { "id": "uuid", "label": "Language", "optional": false },
    { "id": "uuid", "label": "FocusArea", "optional": true }
  ],
  "raw_tokens_in_template": ["[[Language]]", "[[Code]]", "[[FocusArea!]]"]
}

archive_lens

Archive a lens. Archived lenses are excluded from listings but not deleted — they can be restored.

ParameterTypeRequiredDescription
lens_idUUIDYesThe lens to archive

Returns: { lens_id, status: 'archived' }

Error codes: NOT_FOUND · FORBIDDEN


delete_lens

Soft-delete a lens. Requires explicit confirmation to prevent accidental deletion.

ParameterTypeRequiredDescription
lens_idUUIDYesThe lens to delete
confirmtrue (literal boolean)YesMust be exactly true

Returns: { deleted: true, ... }

The lens record is marked as deleted and excluded from all queries. It is not physically removed from the database.

Error codes: NOT_FOUND · FORBIDDEN


set_lens_visibility

Change the visibility tier of a lens.

ParameterTypeRequiredDescription
lens_idUUIDYesThe lens to update
visibility'public' | 'community' | 'private'YesNew visibility tier

Returns: { lens_id, visibility }

Visibility tiers:

TierAccessible to
publicEveryone including unauthenticated users
communityAuthenticated LenserFight members only
privateOnly the owning lenser

list_lens_versions

List all versions of a lens, ordered newest first.

ParameterTypeRequiredDescription
lens_idUUIDYesThe lens whose versions to list

Returns: [{ id, semver, created_at, changelog }]


get_lens_version

Get full details of a specific lens version, including template body and parameter list.

ParameterTypeRequiredDescription
lens_idUUIDYesThe parent lens
version_idUUIDNoVersion UUID (one of version_id or semver required)
semverstringNoSemantic version string e.g. "1.2.0"

Returns:

json
{
  "id": "...",
  "semver": "1.2.0",
  "template_body": "...",
  "changelog": "Added FocusArea parameter.",
  "created_at": "2026-05-01T00:00:00Z",
  "version_parameters": [
    { "id": "...", "label": "Language", "optional": false }
  ]
}

Error codes: BAD_INPUT (neither version_id nor semver provided) · NOT_FOUND


Battle tools

list_battles

List battles with optional filters and pagination.

ParameterTypeRequiredDefaultDescription
limitnumber (1–100)No20Results per page
offsetnumberNo0Pagination offset
status'draft' | 'open' | 'executing' | 'voting' | 'scoring' | 'closed' | 'published' | 'archived'NoFilter by lifecycle status
battle_type'ai_vs_ai' | 'human_vs_human_ai_votes' | 'human_vs_human_open_votes' | 'human_vs_ai' | 'workflow_battle' | 'lenser_battle'NoFilter by battle format
creator_lenser_idUUIDNoFilter to a specific creator

Returns: Paginated list of battle summaries.


get_battle

Get full battle details including contenders, vote aggregates, and all submissions.

ParameterTypeRequiredDescription
battle_idUUIDYesThe battle to retrieve

Returns: Battle object with contenders, vote_aggregates, submissions, and related lenser/model maps.


create_battle

Create a new battle. The task_prompt is the challenge all contenders must respond to.

ParameterTypeRequiredDefaultDescription
titlestring (1–200 chars)YesDisplay name
task_promptstring (1–32 000 chars)YesThe challenge / question all contenders respond to
battle_typesee list_battlesNo'ai_vs_ai'Format of the battle
judging_mode'community_vote' | 'ai_judge' | 'rubric_score' | 'auto_score'No'ai_judge'How responses are evaluated
max_contendersnumber (2–26)No2Maximum contender slots
ai_judge_model_keystringNoSpecific model key for the AI judge

Returns: { id: battle_id, title }

Battle types:

TypeDescription
ai_vs_aiTwo or more AI models compete
human_vs_human_ai_votesHumans compete, AI judges the responses
human_vs_human_open_votesHumans compete, community votes
human_vs_aiA human competes against an AI
workflow_battleWorkflows compete against each other
lenser_battleLensers compete directly

add_battle_contender

Add an AI model, lenser, or workflow as a contender. Slots are auto-assigned A, B, C … Z.

ParameterTypeRequiredDescription
battle_idUUIDYesThe battle to add a contender to
display_namestring (1–100 chars)YesHuman-readable label
contender_type'human' | 'ai_model' | 'ai_agent'YesThe kind of contender
contender_ref_idUUIDYesProfile UUID for human; AI lenser UUID for ai_model / ai_agent
slotstring (single A–Z char)NoAuto-assigned if omitted

Returns: { contender_id, slot_label, battle_id }

Error codes: SLOTS_FULL · FORBIDDEN


submit_battle_run

Submit a contender's response to the battle's task_prompt.

ParameterTypeRequiredDescription
battle_idUUIDYesThe battle
contender_idUUIDYesThe contender submitting
content_textstring (1–100 000 chars)YesThe contender's response

Returns: { submitted: true, ... }

All contenders submitting while the battle is executing triggers the scoring pipeline automatically.


get_battle_score

Read vote aggregates and AI judge verdicts for a battle.

ParameterTypeRequiredDescription
battle_idUUIDYesThe battle to score

Returns:

json
{
  "battle_id": "...",
  "vote_aggregates": [
    { "contender_id": "...", "vote_count": 47, "vote_score": 4.2 }
  ],
  "ai_judge_verdicts": [
    {
      "contender_id": "...",
      "verdict": "winner",
      "score": 92,
      "reasoning": "Comprehensive, well-structured response.",
      "created_at": "2026-05-28T12:00:00Z"
    }
  ]
}

set_battle_status

Transition a battle to a new lifecycle status. Transitioning to closed or archived requires confirm: true.

ParameterTypeRequiredDescription
battle_idUUIDYesThe battle to update
status'open' | 'executing' | 'voting' | 'scoring' | 'closed' | 'published' | 'archived'YesTarget status
confirmtrue (literal)ConditionalRequired when transitioning to 'closed' or 'archived'

Returns: { battle_id, status }

Valid transitions:

draft → open → executing → voting → scoring → closed → published

                                               (any) → archived

Error codes: CONFIRMATION_REQUIRED · NOT_FOUND · FORBIDDEN · INVALID_TRANSITION


get_battle_history

List battles a lenser created or participated in as a contender.

ParameterTypeRequiredDefaultDescription
lenser_idUUIDNoLENSERFIGHT_LENSER_ID env varThe lenser whose history to retrieve
limitnumber (1–100)No20Results per page
offsetnumberNo0Pagination offset
status'closed' | 'published' | 'archived'NoFilter by final status

Returns: Paginated list of historical battles.


Workflow tools

list_workflows

List workflows with optional filters and pagination.

ParameterTypeRequiredDefaultDescription
limitnumber (1–100)No20Results per page
offsetnumberNo0Pagination offset
visibility'public' | 'private' | 'unlisted'NoFilter by visibility
lenser_idUUIDNoFilter to a specific owner

Returns: Paginated list of workflow summaries.


get_workflow

Get full details of a workflow including its head version and scheduling metadata.

ParameterTypeRequiredDescription
workflow_idUUIDYesThe workflow to retrieve

Returns: Workflow object with head version details and scheduling configuration.


create_workflow

Create a new workflow as a reusable multi-step execution container.

ParameterTypeRequiredDefaultDescription
titlestring (1–200 chars)YesDisplay name
descriptionstring (max 2 000 chars)NoHuman-readable description
visibility'public' | 'private' | 'unlisted'No'private'Initial visibility
lenser_idUUIDNoLENSERFIGHT_LENSER_ID env varOwner of the workflow

Returns: New workflow object.

Error codes: MISSING_LENSER


run_workflow

Start a workflow execution. Returns a run_id immediately; poll get_workflow_run_status for completion.

ParameterTypeRequiredDefaultDescription
workflow_idUUIDYesThe workflow to execute
inputsRecord<string, unknown>No{}Input values for the first node
global_model_idstringNoOverride model for all AI nodes
idempotency_keystring (max 128 chars)NoReturns an existing run if a run with this key already exists

Returns:

json
{
  "id": "run-uuid",
  "status": "pending",
  "created_at": "2026-05-28T12:00:00Z",
  "workflow_id": "..."
}

get_workflow_run_status

Poll the current status and credit cost of a running or completed workflow run.

ParameterTypeRequiredDescription
run_idUUIDYesThe run to poll

Returns:

json
{
  "id": "run-uuid",
  "status": "running",
  "started_at": "2026-05-28T12:00:00Z",
  "completed_at": null,
  "spent_credits": 12,
  "budget_credits": 100,
  "cost_metadata": { "model_calls": 3, "tokens_used": 1840 }
}

Status values:

StatusMeaning
pendingQueued, not yet started
runningActively executing
completedAll nodes finished successfully
failedOne or more nodes failed — use get_workflow_run_logs
cancelledManually cancelled

get_workflow_run_logs

Read per-node execution logs for a run, ordered by start time.

ParameterTypeRequiredDescription
run_idUUIDYesThe run to inspect

Returns:

json
{
  "run": { "id": "...", "status": "completed", "cost_metadata": {...} },
  "node_results": [
    {
      "node_id": "...",
      "status": "completed",
      "output": { "text": "..." },
      "tokens_used": 620,
      "cost_credits": 4,
      "started_at": "...",
      "completed_at": "..."
    }
  ]
}

retry_workflow

Retry a failed or cancelled run with the same inputs. Creates a new run linked to the original via parent_run_id.

ParameterTypeRequiredDescription
run_idUUIDYesThe failed or cancelled run to retry

Returns:

json
{
  "new_run": { "id": "new-run-uuid", "status": "pending", "created_at": "..." },
  "original_run_id": "..."
}

Error codes: NOT_FOUND


summarize_workflow

Aggregate run metrics: overall status, wall-clock duration, credit cost, and per-node result counts.

ParameterTypeRequiredDescription
run_idUUIDYesThe run to summarize

Returns:

json
{
  "run_id": "...",
  "workflow_id": "...",
  "status": "completed",
  "duration_ms": 8420,
  "spent_credits": 12,
  "budget_credits": 100,
  "cost_metadata": { "model_calls": 3, "tokens_used": 1840 },
  "nodes": { "total": 5, "completed": 5, "failed": 0, "skipped": 0 }
}

Error codes: NOT_FOUND


Agent tools

The 12 agent tools manage AI Lensers (AI Agents). Full per-tool reference lives in tools-agent — this section links each one with its safety class and underlying RPC so providers can plan permission UIs.

ToolClassRPC
list_ai_lensersReadpublic.fn_list_agents_by_owner
get_ai_lenserReadpublic.fn_get_agent_profile
list_agent_toolsReadpublic.fn_list_agent_tools
list_agent_run_eventsReadpublic.fn_agent_run_events
create_ai_lenserWritepublic.fn_create_ai_lenser
update_ai_lenserWritepublic.fn_update_agent_profile
assign_agent_toolWritepublic.fn_assign_tool
run_agent_actionExecuteagents.fn_agent_action (authenticated)
start_agent_team_runExecuteagents.fn_start_team_run (service_role only)
archive_ai_lenserDestructivepublic.fn_archive_agent
revoke_agent_toolDestructivepublic.fn_revoke_tool
cancel_agent_runDestructivepublic.fn_cancel_agent_run

The agents schema is exposed in supabase/config.toml alongside public, so PostgREST routes both. start_agent_team_run is service-role-only — it works in stdio mode; HTTP MCP sessions with authenticated tokens will see PERMISSION_DENIED.


Common error codes

CodeMeaning
NOT_FOUNDThe resource does not exist or is not accessible to the authenticated user
FORBIDDENThe user does not own or have write access to the resource
MISSING_PARAMSA run_lens call is missing required parameter values; response includes missing list
MISSING_LENSERNo lenser_id was provided and LENSERFIGHT_LENSER_ID is not set
SLOTS_FULLAll 26 contender slots in a battle are assigned
CONFIRMATION_REQUIREDA destructive transition requires confirm: true
INVALID_TRANSITIONThe requested status transition is not allowed in the battle lifecycle
BAD_INPUTRequired input combination not satisfied (e.g., neither version_id nor semver provided)
CONFLICTA uniqueness constraint blocked the call (e.g., create_ai_lenser with a handle already in use)
THROTTLEDA daily quota was exhausted (e.g., start_agent_team_run after the agent's daily team-run cap)