flconsole MCP server
On this page
The flconsole MCP server gives your AI agent new Upwork jobs and your job feeds. Your agent finds new jobs, reads them and shows you the ones that fit. This page lists every tool, argument, filter and limit.
Overview
| Setting | Value |
|---|---|
| Server URL | https://mcp.lite.flconsole.com/mcp |
| Transport | Streamable HTTP |
| Sign-in | Through Telegram: no password, no API key |
| Price | Free |
- New jobs only. The server returns jobs posted in the last 30 minutes. There is no search in older jobs.
- Your agent asks; the server doesn't push. The agent checks for new jobs when you ask it or on a schedule. For alerts within a minute of posting, use the Telegram bot.
- Feeds are shared with Telegram. A feed your agent creates shows up in the bot under
/feeds, and its alerts arrive in Telegram. Up to 5 feeds in total. - No access to your Upwork account. flconsole never asks for your Upwork login and can't act in your account.
- Your agent does the reading. Filters are structured JSON. Picking jobs by meaning is done by your agent, not by the server.
Connect
Add the server to your client, then sign in. Sign-in works the same way everywhere:
- Your client opens a sign-in page in the browser.
- Tap Continue in Telegram (or scan the QR code with your phone). The flconsole bot opens. If you're new, tap Start — that's all it takes.
- The bot names the app that wants access. Tap Allow, and the bot shows a 4-digit code.
- Enter the code on the sign-in page. Your client is connected.
The sign-in link works for 10 minutes. After 5 wrong codes the request is cancelled; start again in your client.
Claude Code
claude mcp add --transport http flconsole https://mcp.lite.flconsole.com/mcpAdd --scope user to make the server available in all your projects. Then run /mcp in Claude Code, pick flconsole and choose Authenticate.
To check jobs on a schedule: /loop 10m check new jobs in my feeds and show only relevant ones. Step-by-step guide: flconsole in Claude Code.
Codex
codex mcp add flconsole --url https://mcp.lite.flconsole.com/mcp
codex mcp login flconsoleThe second command opens the sign-in page in your browser. Guide: flconsole in Codex.
Claude app
Web, desktop and mobile: Settings → Connectors → Add custom connector, then paste https://mcp.lite.flconsole.com/mcp. The app opens the sign-in page. Guide: flconsole in the Claude app.
Cursor
Add the server to ~/.cursor/mcp.json:
{
"mcpServers": {
"flconsole": { "url": "https://mcp.lite.flconsole.com/mcp" }
}
}Then sign in from Cursor's MCP settings when it asks. Guide: flconsole in Cursor.
Other clients
Any MCP client with Streamable HTTP works. If it supports sign-in (OAuth), add the server URL and sign in as above. If it doesn't, use a manual token.
Manual token
For clients without sign-in support. In the Telegram bot, send /mcp and tap Manual token (other apps). The bot shows the token once and doesn't store it, together with ready-to-paste commands.
Send it as a header: Authorization: Bearer <token>.
Claude Code:
claude mcp add --transport http flconsole https://mcp.lite.flconsole.com/mcp \
--header "Authorization: Bearer <token>"Codex, in ~/.codex/config.toml, with the token in an environment variable:
[mcp_servers.flconsole]
url = "https://mcp.lite.flconsole.com/mcp"
bearer_token_env_var = "FLCONSOLE_MCP_TOKEN"export FLCONSOLE_MCP_TOKEN=<token>Lost or leaked a token? Revoke it in /mcp and create a new one. Manual tokens and sign-ins share the limit of 5 connections.
Tools
The server has 11 tools.
| Tool | What it does | Limit |
|---|---|---|
find_jobs | New jobs by a feed, all feeds or any filters | 100 jobs an hour, 1,000 a day |
get_job_details | Full data for the jobs you picked | 30 details an hour |
list_feeds | Your feeds with filters and status | None |
create_feed | Creates a feed; needs your approval | 20 changes an hour |
update_feed | Changes, pauses or resumes a feed | 20 changes an hour |
delete_feed | Deletes a feed; needs your approval | 20 changes an hour |
preview_filters | How many jobs matched in the last hours, with samples | 10 an hour |
parse_upwork_url | Turns an Upwork search link into filters | 30 an hour |
list_categories | Upwork categories and subcategories | None |
find_locations | Countries and regions by name | None |
get_usage | What's left of your limits | None |
Every tool also counts toward 60 calls a minute per connection.
find_jobs
Returns new jobs from one feed, from all your feeds, or by filters you pass in the call. Pass exactly one source: feed_id, all_feeds or filters.
| Argument | Type | Required | What it does |
|---|---|---|---|
feed_id | integer | No | One feed |
all_feeds | boolean | No | All your feeds |
filters | object | No | Any filters, without a feed |
cursor | string | No | Only with filters: cursor from the previous response |
lookback_minutes | integer | No | Only with filters and without cursor; default and maximum 30 |
limit | integer | No | 1–30, default 10; capped by the remaining quota |
- Each call returns only jobs newer than the previous check, and never jobs older than 30 minutes. Jobs come oldest first, as short cards.
- With
feed_idorall_feeds, the server remembers where each feed stopped, separately for each connection. Each job lists the feeds it matched inmatched_feeds. Paused feeds are checked too. - With
filters, nothing is saved. Pass thecursorfrom the response into the next call to get only newer jobs. - A feed's AI filter applies to Telegram alerts only.
find_jobsdoesn't apply it: your agent judges the jobs itself. - The response also has
skipped_count, yourquotafor the hour and the day, andnext_check_after.
Limit100 jobs an hour, 1,000 a day, one call every 60 seconds
get_job_details
Full data of jobs returned by find_jobs: experience level, duration, workload, category and client statistics. Use it for the few jobs worth a closer look, not for every job found.
| Argument | Type | Required | What it does |
|---|---|---|---|
upwork_ids | array of strings | Yes | 1–5 upwork_id values from find_jobs |
Every requested job counts toward the quota, including ones that weren't found. Jobs that weren't found are listed in not_found.
Limit30 jobs an hour
list_feeds
Your feeds: feed_id, name, filters, a one-line summary, AI filter and status. No arguments.
telegram_delivery shows whether Telegram alerts are on: active, paused (this feed is paused), stopped (you sent /stop) or blocked (you blocked the bot). The response also has your feed limit.
create_feed
Creates a feed: a saved search in the Telegram bot that sends you an alert about every new matching job. To just look at jobs in your agent, use find_jobs with filters instead: no feed needed.
| Argument | Type | Required | What it does |
|---|---|---|---|
filters | object | Yes | Complete filters; base.q is required |
name | string | No | Up to 40 characters; automatic if omitted |
ai_filter | string | No | AI filter rules in plain words, up to 2,000 characters |
is_active | boolean | No | Default true; false creates the feed paused |
user_confirmed | boolean | Yes | true only after you agreed to a feed with Telegram alerts |
You get a message in Telegram about the new feed.
Limit20 feed changes an hour (create, update and delete together)
update_feed
Changes a feed's name, filters or AI filter, or pauses and resumes it. Pass at least one of name, filters, ai_filter, is_active.
| Argument | Type | Required | What it does |
|---|---|---|---|
feed_id | integer | Yes | Feed id from list_feeds |
filters | object | No | Replaces the saved filters entirely: send the full object |
name | string | No | New name |
ai_filter | string | No | Replaces the AI filter; "" removes it; omit to keep it |
is_active | boolean | No | false pauses, true resumes |
user_confirmed | boolean | Yes | true only after you approved this exact change |
You get a message in Telegram about what changed.
Limit20 feed changes an hour
delete_feed
Deletes a feed.
| Argument | Type | Required | What it does |
|---|---|---|---|
feed_id | integer | Yes | Feed id from list_feeds |
user_confirmed | boolean | Yes | true only after you approved deleting this feed |
You get a message in Telegram about the deleted feed.
Limit20 feed changes an hour
preview_filters
How many jobs matched the filters in the last hours, with up to 3 short samples. Use it to check filters before creating a feed or calling find_jobs.
| Argument | Type | Required | What it does |
|---|---|---|---|
filters | object | Yes | Filters to check |
window_hours | integer | No | 1–24, default 24 |
Each sample has the title, link, job type, rate or budget, posting time and the client's country, total spent and rating.
Limit10 calls an hour
parse_upwork_url
Turns an Upwork job search link into filters. Open upwork.com/nx/search/jobs, set your search and filters, and copy the address.
| Argument | Type | Required | What it does |
|---|---|---|---|
url | string | Yes | Upwork job search link |
Returns filters, a readable list of them, a suggested feed name and any link parameters that weren't recognized. A link to a single job is not a search link.
Limit30 calls an hour
list_categories
Upwork categories and subcategories with their upwork_id, for base.category2_uid and base.subcategory2_uid. No arguments.
find_locations
Finds countries, subregions and regions by name or alias, for base.location.
| Argument | Type | Required | What it does |
|---|---|---|---|
query | string | Yes | Part of a name, 1–100 characters |
Returns up to 30 matches with type (country, subregion or region), aliases and the region each belongs to.
get_usage
What's left of your hourly and daily quotas, when the next find_jobs is allowed, and your feed count and limit. No arguments.
Filters
create_feed, update_feed, preview_filters and find_jobs take the same filters object:
{
"schema_version": 1,
"base": {
"q": "elevenlabs OR vapi OR retell",
"t": ["hourly"],
"hourly_rate": { "min": 40, "max": null },
"contractor_tier": ["expert"],
"location": { "include": ["United States", "Western Europe"], "exclude": [] },
"payment_verified": true
},
"advanced": {
"cl_total_spent": { "min": 10000, "max": null },
"cl_rating": { "min": 4.5, "max": null }
}
}schema_versionis required and is always1.- A key that is omitted,
nullor[]is not set. Yes/no filters taketrue,falseornull(any). - Ranges are
{ "min": …, "max": … }; either side can benull. - Unknown keys are rejected with
invalid_filters, so a typo never silently filters nothing. - Client filters: a client without that statistic doesn't match a range.
base
| Key | Type | What it filters |
|---|---|---|
q | string | Search query, required. See search syntax |
category2_uid | array of strings | Categories: upwork_id from list_categories |
subcategory2_uid | array of strings | Subcategories: upwork_id from list_categories |
t | array | Job type: hourly, fixed |
contractor_tier | array | Experience level: entry, intermediate, expert |
amount | range | Fixed budget, $ |
hourly_rate | range | Hourly rate, $ |
client_hires | array of ranges | Client's number of hires; any of the ranges |
workload | array | Hours per week: less_than_30_hours, more_than_30_hours |
duration_v3 | array | Project length: less_than_one_month, 1_to_3_months, 3_to_6_months, more_than_6_months |
contract_to_hire | boolean | Contract-to-hire jobs |
location | object | include and exclude: country, subregion or region names from find_locations |
payment_verified | boolean | Client's payment method verified |
A job matches if it is in any of the listed categories or subcategories.
advanced
| Key | Type | What it filters |
|---|---|---|
cl_total_spent | range | Client's total spent, $ |
cl_rating | range | Client's rating, 0–5 |
cl_review_cnt | range | Number of reviews |
cl_hire_rate | range | Hire rate, % |
cl_registered_at | object | Account age: max_days_ago: 1095 = older than 3 years; min_days_ago: 30 = newer than 30 days |
cl_avg_hourly | range | Average hourly rate paid, $ |
cl_paid_hours | range | Hours paid |
cl_posted_jobs_cnt | range | Jobs posted |
cl_open_jobs_cnt | range | Open jobs |
cl_hires_cnt | range | Hires |
cl_active_hires_cnt | range | Active hires |
cl_work_history_cnt | range | Jobs in work history |
cl_avg_spent_per_hire | range | Total spent divided by hires, $ |
cl_phone_verified | boolean | Phone verified |
cl_enterprise | boolean | Enterprise client |
has_questions | boolean | Job has screening questions |
has_attachments | boolean | Job has attachments |
Search syntax
base.q works like the search box on Upwork:
react native both words
"voice agent" exact phrase
vapi OR retell any of them
python NOT wordpress exclude a word- At least 3 letters: a shorter search matches almost every job.
- Not only exclusions:
NOT wordpressalone is rejected. Add words to look for. - Up to 1,000 characters. Parentheses group terms:
(vapi OR retell) AND voice. - Search in English: Upwork jobs are posted in English.
- Upwork search can't read field names like
skills:, the characters/ [ ] ~, or*at the start of a word. Such a query is rejected withinvalid_query. - Rates, locations and client requirements belong in filters, not in the search.
Job fields
find_jobs returns short cards: enough to judge a job by its text. get_job_details adds the terms and the client's history.
| Field | Short card | Full details |
|---|---|---|
upwork_id, link, title | Yes | Yes |
description | Up to 5,000 characters, with description_truncated | Full text |
skills | Yes | Yes |
job_type, hourly_rate_from, hourly_rate_to, fixed_budget | Yes | Yes |
publish_at | Yes | Yes |
matched_feeds | With feed_id or all_feeds | None |
experience_level, project_length, workload, contract_to_hire | None | Yes |
has_questions, has_attachments, category | None | Yes |
client.country | Yes | Yes |
| Other client data | None | City, payment and phone verified, enterprise, rating, reviews, total spent, average hourly rate paid, hours paid, hire rate, account creation date, jobs posted, open jobs, hires, active hires, work history, company size and industry |
The client's name is never returned. link is a short flconsole link that opens the job on Upwork; if a short link can't be made, it is the direct upwork.com link.
Limits
| What | Limit |
|---|---|
Jobs via find_jobs | 100 an hour and 1,000 a day, across all feeds, filters and connections |
Full job details (get_job_details) | 30 jobs an hour, up to 5 per call |
| Job age | Posted in the last 30 minutes; no search in older jobs |
| Checks for new jobs | At most once every 60 seconds; every 5–15 minutes is enough for monitoring |
find_jobs with filters, no feed | At most 100 matches in the window, otherwise filters_too_broad |
| Feeds | 5, shared with Telegram; paused feeds count too |
| Feed changes (create, update, delete) | 20 an hour |
preview_filters | 10 an hour |
parse_upwork_url | 30 an hour |
| All tool calls | 60 a minute per connection |
| Connections | 5: sign-ins and manual tokens together |
Hourly quotas reset at the start of each hour (UTC), the daily quota at midnight UTC. get_usage shows what's left. MCP quotas don't affect Telegram alerts, and Telegram alerts don't use MCP quotas.
The server enforces these limits; your agent can't lift them, even if you ask.
Errors
A failed call returns a normal tool result marked as an error, so your agent can read it and fix the call:
{ "error": { "code": "filters_too_broad", "message": "…", "field": "filters", "retry_after_seconds": 60 } }field and retry_after_seconds appear when they apply.
| Code | What it means |
|---|---|
invalid_request | An argument is missing or wrong; field names it |
invalid_filters | A filter is unknown or has a wrong value; field is its path, like base.hourly_rate |
invalid_query | Upwork search can't read base.q, or it is too short or too long |
not_found | No such feed among yours |
confirmation_required | create_feed, update_feed or delete_feed without user_confirmed: true |
too_early | Checked again sooner than 60 seconds |
quota_exhausted | The hourly or daily find_jobs quota is used up |
rate_limited | Another hourly limit is used up, or more than 60 calls a minute |
filters_too_broad | Filters without a feed match more than 100 new jobs |
unavailable | Temporary problem on our side; try again later |
filters_too_broad
Your filters without a feed match more than 100 jobs in the window. Nothing is returned and no quota is used. Put every criterion into filters: category, job type, rate or budget, experience level, location, client statistics. Make the search more specific with OR, AND and parentheses. preview_filters shows how many jobs a set of filters matches. Try again after retry_after_seconds.
Quota exceeded
quota_exhausted means the 100 jobs for this hour or the 1,000 for today have already been returned. The message says when the quota resets; retry_after_seconds is the wait. get_job_details and the other tools answer rate_limited when their hourly limit is used up. Narrow your filters so fewer, better jobs use the quota.
skipped_count
skipped_count above 0 means more jobs matched than were returned. The skipped jobs are not returned later. The response then also has a warning. Narrow the filters or the feed's search so that everything that matches fits into one response.
Too frequent checks
too_early means less than 60 seconds have passed since your last check. Wait retry_after_seconds. Nothing is lost: the next check returns the jobs posted in between. For regular monitoring, a check every 5–15 minutes is enough.
Security
- Sign-in through Telegram. You approve each new connection in the bot and enter a 4-digit code on the sign-in page. Never share the code: whoever has it gets access to your feeds.
- No password, no API key. Connections use tokens; flconsole stores only their hashes. A sign-in session lasts up to 90 days from its last use.
- Every feed change is reported in Telegram. When your agent creates, changes, pauses, resumes or deletes a feed, the bot tells you. You see it even after
/stop, so you notice a connection you didn't make. - Your approval for every write.
create_feed,update_feedanddelete_feedrequireuser_confirmed: true, which your agent may pass only after you agreed in the conversation. - Disconnect any time. In the bot, send
/mcp: it lists your connections with the date they were created and last used. Disconnect one, and it loses access right away. Your feeds stay. - No access to your Upwork account. The server only reads public job data and your flconsole feeds.
See also: Privacy.
Good to know
Can the agent search old jobs?
No. Only jobs posted in the last 30 minutes.
Does my agent get jobs pushed to it?
No. It checks when you ask or on a schedule. Telegram alerts arrive within a minute.
What does the agent see about a job?
Title, description, skills, job type, budget or rate, and the client's country. Full details are available for the jobs it picks.
How do I disconnect an agent?
In the Telegram bot: /mcp.
Connect your agent
Claude Code
claude mcp add --transport http flconsole https://mcp.lite.flconsole.com/mcpThen run /mcp → Authenticate. You'll confirm in Telegram — no password, no token.
Codex
codex mcp add flconsole --url https://mcp.lite.flconsole.com/mcpcodex mcp login flconsole
A browser opens — confirm in Telegram and you're in.
Claude app
Settings → Connectors → Add custom connector
https://mcp.lite.flconsole.com/mcpWorks on web, desktop and mobile. You'll confirm in Telegram.
Cursor
{"mcpServers": {"flconsole": {"url": "https://mcp.lite.flconsole.com/mcp"}}}
Add it to ~/.cursor/mcp.json, then sign in when Cursor asks.
Free · Sign in with Telegram · No API key