Settings
This page is for the administrator. It lists every setting of an installation: its key in config.json, the environment variable that overrides it, and what it is when you set nothing.
You do not need this page to run Marketing MCP. The management page sets almost all of these, and each section below names the page. Use this page when you set up a server by script, or when you want to know what a line in config.json means.
These are the settings of the whole installation. What belongs to one person (their password, their connections to Google, Meta and LinkedIn, whether they may write, their tokens) is not a setting: it is in the database, and you manage it on Users and each person manages it on their own pages.
Where settings come from
A setting is looked for in three places, in this order:
- An environment variable. If it is set and not empty, it wins.
config.json. The management page writes this file when you press a save button.- The default in the tables below.
An environment variable wins over the management page
While a variable is set, saving that setting on the management page changes the file and not what the server does. Remove the variable to let the page decide.
The server reads environment variables when it starts, so a changed variable needs a restart. A file named .env in the folder the server is started from is read as well.
A change saved on the management page takes effect at once, except the bind address, the port and read-only mode, which need a restart.
Where config.json is
- For the executable: in the same folder as the executable. If that folder cannot be written to, the per-user folder below is used instead.
- When it is installed as a Python package:
%APPDATA%\nama-marketing-mcpon Windows,~/.config/nama-marketing-mcpon Linux.
The database, the media library and the kept reports are in the same folder unless you move them. Three variables change where things are, and have no key in the file:
| Environment variable | What it does |
|---|---|
NAMA_MCP_HOME | The folder that holds config.json, the database, the media library and the kept reports. |
NAMA_MCP_CONFIG | The full path of the settings file, when it is not config.json in that folder. |
NAMA_MCP_ENV_FILE | The full path of the .env file to read, when it is not in the folder the server is started from. |
The file holds secrets (the app secrets, the webhook secrets, the mail password). Where the operating system allows, the server makes it readable by its own user only. Do not copy it into a place others can read.
How values are written
The file is JSON with one object a section: "server", "google_ads", "meta" and so on. A key in the tables below goes inside its section's object:
{
"server": { "port": 8765, "public_url": "https://ads.example.com" },
"meta_ads": { "enabled": true, "max_daily_budget": { "USD": 100, "SAR": 375 } }
}| Kind of value | In config.json | In an environment variable |
|---|---|---|
| Switch | true or false | true, 1, yes or on for on; anything else is off |
| Limit (a number) | A number. null means no limit. | A number. An empty variable counts as not set, so "no limit" can only be said in the file or on the page. |
| Money limit by currency | An object: {"USD": 100, "SAR": 375} | USD=100,SAR=375 |
| List | A list: ["KW", "SA"] | Separated by commas: KW,SA |
| List of folders | A list of paths | Separated by ; on Windows and : on Linux |
A money limit by currency has no entry for "every currency". An ad account whose currency has no entry is not unlimited: the changes that limit guards are refused for it until you add its currency.
Server
Section server. Set on Server, except read_only, which is on Safety limits, and the three paths, which are set only here or in the environment. See Server settings.
| Key | Environment variable | Default | What it is |
|---|---|---|---|
host | NAMA_MCP_HOST | 127.0.0.1 | The bind address. 127.0.0.1 is this machine only; 0.0.0.0 is every interface. Needs a restart. Starting the server with --host overrides it for that run. |
port | NAMA_MCP_PORT | 8765 | The port. Needs a restart. Starting the server with --port overrides it for that run. |
public_url | NAMA_MCP_PUBLIC_URL | none | The public address, such as https://ads.example.com, when people reach the server through a name or a reverse proxy. |
read_only | NAMA_MCP_READ_ONLY | false | Read-only mode (Refuse every change on Safety limits): no tool that changes a platform is offered, to anyone. Needs a restart. |
data_dirs | NAMA_MCP_DATA_DIR | none | Data folders: the folders a file of customer records may be read from. A list of folders. |
db_path | NAMA_MCP_DB_PATH | nama-marketing.db in the installation folder | The database file: users, tokens, the activity log and everything else the server stores. |
media_path | NAMA_MCP_MEDIA_PATH | media in the installation folder | The folder that holds the media library. |
reports_path | NAMA_MCP_REPORTS_PATH | reports in the installation folder | The folder that holds scheduled reports kept as files. |
Post queue
Section queue. Set on Safety limits.
| Key | Environment variable | Default | What it is |
|---|---|---|---|
max_late_hours | NAMA_MCP_QUEUE_MAX_LATE_HOURS | 24 | How late a queued post may still be published by itself, in hours. A post found later than this waits for a person. No limit means it is published however late. |
History
Section history. Set on Server.
| Key | Environment variable | Default | What it is |
|---|---|---|---|
enabled | NAMA_MCP_HISTORY_ENABLED | false | Whether the server may read accounts by itself, on a timer, for the people who ask it to watch one. |
retention_days | NAMA_MCP_HISTORY_RETENTION_DAYS | 800 | How many days a stored figure and a kept report are kept. No limit means for good. LinkedIn's figures are deleted after a year whatever this says. |
max_watches_per_user | NAMA_MCP_HISTORY_MAX_WATCHES_PER_USER | 20 | How many accounts one person may have watched. |
Notification delivery
Section notify. Set on Notification delivery. All of it is optional: without it, notifications are still shown on Notifications.
| Key | Environment variable | Default | What it is |
|---|---|---|---|
webhook_url | NOTIFY_WEBHOOK_URL | none | The address every notification is sent to. It must be HTTPS and public unless webhook_allow_private is on. |
webhook_secret | NOTIFY_WEBHOOK_SECRET | none | The secret each notification is signed with, so the receiver can tell it came from this server. |
webhook_allow_private | NOTIFY_WEBHOOK_ALLOW_PRIVATE | false | Says the receiver is on this server's own network, so a private address is allowed. |
smtp_host | NOTIFY_SMTP_HOST | none | The mail server. |
smtp_port | NOTIFY_SMTP_PORT | 587 | The mail server's port. |
smtp_security | NOTIFY_SMTP_SECURITY | starttls | How the connection is secured: starttls, ssl or none. |
smtp_username | NOTIFY_SMTP_USERNAME | none | The user name for the mail server, if it asks for one. |
smtp_password | NOTIFY_SMTP_PASSWORD | none | The password for the mail server. |
smtp_from | NOTIFY_SMTP_FROM | none | The address mail is sent from. Mail needs this and the mail server. |
admin_email | NOTIFY_ADMIN_EMAIL | none | Where a notice about the installation, not about one person, is mailed. |
Lead delivery
Section leads. Set on Lead delivery.
| Key | Environment variable | Default | What it is |
|---|---|---|---|
push_enabled | NAMA_MCP_LEADS_PUSH_ENABLED | false | Whether the server may send new leads to your own system by itself. It cannot be turned on without an address and a secret. |
webhook_url | NAMA_MCP_LEADS_WEBHOOK_URL | none | The one address leads are sent to. HTTPS, and public unless webhook_allow_private is on. |
webhook_secret | NAMA_MCP_LEADS_WEBHOOK_SECRET | none | The secret every delivery is signed with. At least 16 characters. Without it nothing is sent. |
webhook_allow_private | NAMA_MCP_LEADS_WEBHOOK_ALLOW_PRIVATE | false | Says the receiver is on this server's own network, so a private address is allowed. |
poll_minutes | NAMA_MCP_LEADS_POLL_MINUTES | 5 | How often a lead feed looks for new leads, in minutes. Never less than 2. |
max_feeds_per_user | NAMA_MCP_LEADS_MAX_FEEDS_PER_USER | 10 | How many lead feeds one person may have. |
Links
Section utm. No page of the management page sets this: set it here or in the environment.
| Key | Environment variable | Default | What it is |
|---|---|---|---|
campaign_prefix | NAMA_MCP_UTM_CAMPAIGN_PREFIX | none | A word put in front of every campaign name when a link is tagged. acme gives acme-autumn-offer. |
Google Ads
Section google_ads. The first three are set on Google Ads API, the rest on Safety limits. Money here is in the currency of the Google Ads account, and one number holds for every account.
| Key | Environment variable | Default | What it is |
|---|---|---|---|
developer_token | GOOGLE_ADS_DEVELOPER_TOKEN | none | The developer token Google gives for the Google Ads API. |
client_id | GOOGLE_ADS_CLIENT_ID | none | The OAuth client id everyone signs in to Google through. |
client_secret | GOOGLE_ADS_CLIENT_SECRET | none | The OAuth client secret. |
max_daily_budget | GOOGLE_ADS_MAX_DAILY_BUDGET | no limit | The highest daily budget a change may set. |
max_budget_change_pct | GOOGLE_ADS_MAX_BUDGET_CHANGE_PCT | 50 | The most one change may raise a budget, in percent. |
max_cpc_bid | GOOGLE_ADS_MAX_CPC_BID | no limit | The highest bid a change may set. |
max_target_cpa | GOOGLE_ADS_MAX_TARGET_CPA | no limit | The highest target cost per conversion a change may set. |
max_cpc_bid_ceiling | GOOGLE_ADS_MAX_CPC_BID_CEILING | no limit | The highest bid ceiling a change may give a strategy that bids by itself. |
max_bid_modifier_pct | GOOGLE_ADS_MAX_BID_MODIFIER_PCT | no limit | The most a bid adjustment may raise a bid, in percent. |
max_keywords_per_call | GOOGLE_ADS_MAX_KEYWORDS_PER_CALL | 200 | How many keywords one request may add. |
max_negatives_per_call | GOOGLE_ADS_MAX_NEGATIVES_PER_CALL | 200 | How many negative keywords one request may add. |
new_keywords_paused | GOOGLE_ADS_NEW_KEYWORDS_PAUSED | true | While on, a new keyword is created paused. |
new_ads_paused | GOOGLE_ADS_NEW_ADS_PAUSED | true | While on, a new ad is created paused. |
allow_conversion_action_edits | GOOGLE_ADS_ALLOW_CONVERSION_ACTION_EDITS | false | Whether conversion actions and goals may be created and changed. |
allow_lead_download | GOOGLE_ADS_ALLOW_LEAD_DOWNLOAD | false | Whether the leads of Google lead forms may be read. |
allow_conversion_upload | GOOGLE_ADS_ALLOW_CONVERSION_UPLOAD | false | Whether offline conversions may be sent to Google. While on, the Google sign-in asks for one more permission. |
allow_customer_match | GOOGLE_ADS_ALLOW_CUSTOMER_MATCH | false | Whether Customer Match lists may be made and filled. While on, the Google sign-in asks for the same extra permission. |
Website analytics
Section website. Set on Google Ads API.
| Key | Environment variable | Default | What it is |
|---|---|---|---|
enabled | WEBSITE_ENABLED | false | Whether the Google Analytics 4 and Search Console reports work. While on, the Google sign-in asks for two more permissions. |
allowed_properties | WEBSITE_ALLOWED_PROPERTIES | all | The Google Analytics 4 properties that may be read, by id. A list. Empty means every property a person's login can list. |
allowed_sites | WEBSITE_ALLOWED_SITES | all | The Search Console sites that may be read, as Search Console spells them (https://www.example.com/ or sc-domain:example.com). A list. Empty means all. |
Meta
Section meta. The app, the switches and the media folders are set on Meta app, the limits on Safety limits.
| Key | Environment variable | Default | What it is |
|---|---|---|---|
app_id | META_APP_ID | none | The Meta app's id. |
app_secret | META_APP_SECRET | none | The Meta app's secret. |
api_version | META_API_VERSION | v25.0 | The Graph API version the server talks. Meta retires a version about two years after it is released. |
comments_enabled | META_COMMENTS_ENABLED | false | Whether the sign-in asks for the comment permissions. |
allow_comment_delete | META_ALLOW_COMMENT_DELETE | false | Whether a comment may be deleted. Hiding a comment needs no switch. |
instagram_delete_enabled | META_INSTAGRAM_DELETE_ENABLED | false | Whether the sign-in asks for the permission that deleting an Instagram post needs. |
messaging_enabled | META_MESSAGING_ENABLED | false | Whether the inbox works and the sign-in asks for the messaging permissions. |
hashtag_search_enabled | META_HASHTAG_SEARCH_ENABLED | false | Whether Instagram hashtag search works. It asks for no new permission. |
media_dirs | META_MEDIA_DIR | none | Media folders: the folders on the server a picture or a video may be taken from by its path. A list of folders. |
max_posts_per_day | META_MAX_POSTS_PER_DAY | 20 | Posts one person may publish in 24 hours. |
max_caption_length | META_MAX_CAPTION_LENGTH | 2200 | The longest post text, in characters. |
max_replies_per_day | META_MAX_REPLIES_PER_DAY | 50 | Replies to comments one person may post in 24 hours. |
max_reply_length | META_MAX_REPLY_LENGTH | 1000 | The longest reply to a comment, in characters. |
max_messages_per_day | META_MAX_MESSAGES_PER_DAY | 100 | Private messages one person may send in reply in 24 hours. |
max_message_length | META_MAX_MESSAGE_LENGTH | 1000 | The longest private message, in characters. |
max_upload_mb | META_MAX_UPLOAD_MB | 100 | The largest file the media library takes, in megabytes. |
media_retention_days | META_MEDIA_RETENTION_DAYS | 30 | How many days a file stays in the media library after it was last uploaded or used. |
Meta Ads
Section meta_ads. The first five are set on Meta app, the rest on Safety limits.
| Key | Environment variable | Default | What it is |
|---|---|---|---|
enabled | META_ADS_ENABLED | false | Whether Meta advertising works and the sign-in asks for the advertising permissions. |
read_only | META_ADS_READ_ONLY | false | Reporting only: nothing in Meta Ads can be changed, by anyone. |
allow_lead_download | META_ADS_ALLOW_LEAD_DOWNLOAD | false | Whether leads may be read. While on, the sign-in asks for one more permission. |
allow_conversion_upload | META_ADS_ALLOW_CONVERSION_UPLOAD | false | Whether conversions may be sent to a pixel. |
allow_customer_lists | META_ADS_ALLOW_CUSTOMER_LISTS | false | Whether a customer list may be made and filled as an audience. |
max_daily_budget | META_ADS_MAX_DAILY_BUDGET | none set | The highest daily budget, by currency. |
max_lifetime_budget | META_ADS_MAX_LIFETIME_BUDGET | none set | The highest lifetime budget, by currency. |
max_total_daily_spend | META_ADS_MAX_TOTAL_DAILY_SPEND | none set | The most the running daily budgets of one ad account may add up to, by currency. |
max_budget_change_pct | META_ADS_MAX_BUDGET_CHANGE_PCT | 50 | The most one change may raise a budget, in percent. |
max_campaign_duration_days | META_ADS_MAX_CAMPAIGN_DURATION_DAYS | 90 | The longest an ad set made here may run, in days. |
allowed_ad_accounts | META_ADS_ALLOWED_AD_ACCOUNTS | all | The ad accounts that may be used, by id. A list. Empty means every account a person's login reaches. |
allowed_geo_countries | META_ADS_ALLOWED_GEO_COUNTRIES | all | The countries ads may target, by two-letter code. A list. Empty means any. |
allow_creative_enhancements | META_ADS_ALLOW_CREATIVE_ENHANCEMENTS | false | Whether a request may let Meta alter a creative by itself. |
require_preview_before_activate | META_ADS_REQUIRE_PREVIEW_BEFORE_ACTIVATE | true | While on, an ad can be switched on only by a person who had it previewed in the last 24 hours. |
LinkedIn
Section linkedin. The app and the switches are set on LinkedIn app, the limits on Safety limits.
| Key | Environment variable | Default | What it is |
|---|---|---|---|
client_id | LINKEDIN_CLIENT_ID | none | The LinkedIn app's client id. |
client_secret | LINKEDIN_CLIENT_SECRET | none | The LinkedIn app's client secret. |
api_version | LINKEDIN_API_VERSION | 202609 | The LinkedIn API version, as year and month. LinkedIn retires a version about a year after it is released. |
ads_enabled | LINKEDIN_ADS_ENABLED | false | Whether LinkedIn advertising works and the sign-in asks for the advertising permissions. |
comments_enabled | LINKEDIN_COMMENTS_ENABLED | false | Whether the sign-in asks for the comment permissions. |
max_posts_per_day | LINKEDIN_MAX_POSTS_PER_DAY | 20 | Posts one person may publish in 24 hours. |
max_post_length | LINKEDIN_MAX_POST_LENGTH | 3000 | The longest post text, in characters. |
max_replies_per_day | LINKEDIN_MAX_REPLIES_PER_DAY | 50 | Replies to comments one person may post in 24 hours. |
max_reply_length | LINKEDIN_MAX_REPLY_LENGTH | 1250 | The longest reply to a comment, in characters. |
LinkedIn refuses the whole sign-in for a permission it has not approved
Turn on ads_enabled, comments_enabled or one of the three product switches below only after LinkedIn has approved the app for that product. Until then, nobody can sign in to LinkedIn through this installation.
LinkedIn Ads
Section linkedin_ads. The first five are set on LinkedIn app, the rest on Safety limits. LinkedIn advertising itself is switched on by ads_enabled in the section above.
| Key | Environment variable | Default | What it is |
|---|---|---|---|
read_only | LINKEDIN_ADS_READ_ONLY | false | Reporting only: nothing in LinkedIn Ads can be changed, by anyone. |
allow_audience_network | LINKEDIN_ADS_ALLOW_AUDIENCE_NETWORK | false | Whether a request may show ads on other companies' apps and sites. |
allow_lead_download | LINKEDIN_ADS_ALLOW_LEAD_DOWNLOAD | false | Whether leads may be read. While on, the sign-in asks for one more permission. |
allow_conversion_upload | LINKEDIN_ADS_ALLOW_CONVERSION_UPLOAD | false | Whether conversions may be sent to LinkedIn. While on, the sign-in asks for one more permission. |
allow_matched_audiences | LINKEDIN_ADS_ALLOW_MATCHED_AUDIENCES | false | Whether audiences may be made, filled and deleted. While on, the sign-in asks for one more permission. |
max_daily_budget | LINKEDIN_ADS_MAX_DAILY_BUDGET | none set | The highest daily budget, by currency. |
max_total_budget | LINKEDIN_ADS_MAX_TOTAL_BUDGET | none set | The highest total budget, by currency. |
max_total_daily_spend | LINKEDIN_ADS_MAX_TOTAL_DAILY_SPEND | none set | The most the running daily budgets of one ad account may add up to, by currency. |
max_bid | LINKEDIN_ADS_MAX_BID | none set | The highest bid, by currency. |
max_budget_change_pct | LINKEDIN_ADS_MAX_BUDGET_CHANGE_PCT | 50 | The most one change may raise a budget, in percent. |
max_campaign_duration_days | LINKEDIN_ADS_MAX_CAMPAIGN_DURATION_DAYS | 90 | The longest a campaign made here may run, in days. |
allowed_ad_accounts | LINKEDIN_ADS_ALLOWED_AD_ACCOUNTS | all | The ad accounts that may be used, by id. A list. Empty means every account a person's login reaches. |
allowed_locations | LINKEDIN_ADS_ALLOWED_LOCATIONS | all | The locations ads may target, each by the number LinkedIn gives it. A list. Empty means any. |
require_preview_before_activate | LINKEDIN_ADS_REQUIRE_PREVIEW_BEFORE_ACTIVATE | true | While on, an ad can be switched on only by a person who had it previewed in the last 24 hours. |
What else is in the file
version, at the top, is the format of the file. The server writes it.limits_reviewed, undergoogle_ads, is written when Safety limits is saved. You do not set it.
Left from the single-user version
The first version of Marketing MCP served one person, and kept that person's Google connection in these three variables. They are read once, when the first administrator is created, and handed to that user. After that they do nothing.
| Environment variable | What it was |
|---|---|
GOOGLE_ADS_REFRESH_TOKEN | That person's Google connection. |
GOOGLE_ADS_LOGIN_CUSTOMER_ID | The manager account they worked under. |
GOOGLE_ADS_WRITE_ENABLED | Whether they could make changes. |